001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.config.event;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020import static org.apache.juneau.commons.utils.StringUtils.*;
021import static org.apache.juneau.config.event.ConfigEventType.*;
022
023import java.util.*;
024
025/**
026 * Represents a change to a config.
027 */
028public class ConfigEvent {
029
030   /**
031    * Removes a value from a configuration.
032    *
033    * @param config
034    *    The configuration name.
035    * @param section
036    *    The section name.
037    *    <br>Must not be <jk>null</jk>.
038    * @param key
039    *    The entry name.
040    *    <br>Must not be <jk>null</jk>.
041    * @return
042    *    A new {@link ConfigEvent} object.
043    */
044   public static ConfigEvent removeEntry(String config, String section, String key) {
045      return new ConfigEvent(REMOVE_ENTRY, config, section, key, null, null, null, null);
046   }
047
048   /**
049    * Removes a section from the config.
050    *
051    * @param config
052    *    The configuration name.
053    * @param section
054    *    The section name.
055    * @return
056    *    A new {@link ConfigEvent} object.
057    */
058   public static ConfigEvent removeSection(String config, String section) {
059      return new ConfigEvent(REMOVE_SECTION, config, section, null, null, null, null, null);
060   }
061
062   /**
063    * Sets or replaces a value in a configuration.
064    *
065    * @param config
066    *    The configuration name.
067    * @param section
068    *    The section name.
069    *    <br>Must not be <jk>null</jk>.
070    * @param key
071    *    The entry name.
072    *    <br>Must not be <jk>null</jk>.
073    * @param value
074    *    The entry value.
075    *    <br>Can be <jk>null</jk> to remove an entry.
076    * @param comment
077    *    Optional comment string to add on the same line as the entry.
078    * @param modifiers
079    *    Optional entry modifiers.
080    * @param prelines
081    *    Comment lines that occur before this entry.
082    *    <br>Must not be <jk>null</jk>.
083    * @return
084    *    A new {@link ConfigEvent} object.
085    */
086   public static ConfigEvent setEntry(String config, String section, String key, String value, String modifiers, String comment, List<String> prelines) {
087      return new ConfigEvent(SET_ENTRY, config, section, key, value, modifiers, comment, prelines);
088   }
089
090   /**
091    * Adds a new empty section to the config.
092    *
093    * @param config
094    *    The configuration name.
095    * @param section
096    *    The section name.
097    * @param prelines
098    *    Comment lines that occur before this section.
099    *    <br>Must not be <jk>null</jk>.
100    * @return
101    *    A new {@link ConfigEvent} object.
102    */
103   public static ConfigEvent setSection(String config, String section, List<String> prelines) {
104      return new ConfigEvent(SET_SECTION, config, section, null, null, null, null, prelines);
105   }
106
107   private final ConfigEventType type;
108   private final String config;
109   private final String section;
110   private final String key;
111   private final String value;
112   private final String comment;
113
114   private final List<String> preLines;
115
116   private final String modifiers;
117
118   /**
119    * Constructor.
120    * @param type - The event type.
121    * @param config - The configuration name.
122    * @param section - The section name.
123    * @param key - The entry name.
124    * @param value - The entry value.
125    * @param modifiers - The entry modifiers.
126    * @param comment - Optional comment string to add on the same line as the entry.
127    * @param preLines - Optional comment lines that occur before this entry.
128    */
129   @SuppressWarnings({
130      "java:S107" // Constructor requires 8 parameters for configuration event
131   })
132   protected ConfigEvent(ConfigEventType type, String config, String section, String key, String value, String modifiers, String comment, List<String> preLines) {
133      this.type = type;
134      this.config = config;
135      this.section = section;
136      this.key = key;
137      this.value = value;
138      this.comment = comment;
139      this.preLines = u(cp(preLines));
140      this.modifiers = modifiers;
141   }
142
143   /**
144    * Returns the entry comment.
145    *
146    * @return The entry comment.
147    */
148   public String getComment() { return comment; }
149
150   /**
151    * Returns the configuration name.
152    *
153    * @return The configuration name.
154    */
155   public String getConfig() { return config; }
156
157   /**
158    * Returns the entry name.
159    *
160    * @return The entry name.
161    */
162   public String getKey() { return key; }
163
164   /**
165    * Returns the modifiers on this entry.
166    *
167    * @return
168    *    The modifier characters.
169    *    <br>Can be <jk>null</jk> if the event has no modifiers (e.g. remove/section events, or entries set without modifiers).
170    */
171   public String getModifiers() { return modifiers; }
172
173   /**
174    * Returns the section or entry lines.
175    *
176    * @return An unmodifiable list of the section or entry lines, or <jk>null</jk> if none were supplied.
177    */
178   public List<String> getPreLines() { return preLines; }
179
180   /**
181    * Returns the section name.
182    *
183    * @return The section name.
184    */
185   public String getSection() { return section; }
186
187   /**
188    * Returns the event type.
189    *
190    * @return The event type.
191    */
192   public ConfigEventType getType() { return type; }
193
194   /**
195    * Returns the entry value.
196    *
197    * @return The entry value.
198    */
199   public String getValue() { return value; }
200
201   @Override /* Overridden from Object */
202   public String toString() {
203      return switch (type) {
204         case REMOVE_SECTION -> "REMOVE_SECTION(" + section + ")";
205         case REMOVE_ENTRY -> "REMOVE_ENTRY(" + section + (section.isEmpty() ? "" : "/") + key + ")";
206         case SET_SECTION -> "SET_SECTION(" + section + ", preLines=" + join(preLines, '|') + ")";
207         case SET_ENTRY -> {
208            var out = new StringBuilder("SET(");
209            out.append(section + (section.isEmpty() ? "" : "/") + key);
210            if (nn(modifiers))
211               out.append(modifiers);
212            out.append(" = ");
213            var val = value == null ? "null" : value;
214            if (val.indexOf('\n') != -1)
215               val = val.replaceAll("(\\r?\\n)", "$1\t");
216            if (val.indexOf('#') != -1)
217               val = val.replace("#", "\\#");
218            out.append(val);
219            if (ine(comment))
220               out.append(" # ").append(comment);
221            out.append(')');
222            yield out.toString();
223         }
224         default -> null;
225      };
226   }
227}