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.StringUtils.*;
020import static org.apache.juneau.commons.utils.Utils.*;
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, section, key, value, comment;
109
110   private final List<String> preLines;
111
112   private final String modifiers;
113
114   /**
115    * Constructor.
116    * @param type - The event type.
117    * @param config - The configuration name.
118    * @param section - The section name.
119    * @param key - The entry name.
120    * @param value - The entry value.
121    * @param modifiers - The entry modifiers.
122    * @param comment - Optional comment string to add on the same line as the entry.
123    * @param preLines - Optional comment lines that occur before this entry.
124    */
125   protected ConfigEvent(ConfigEventType type, String config, String section, String key, String value, String modifiers, String comment, List<String> preLines) {
126      this.type = type;
127      this.config = config;
128      this.section = section;
129      this.key = key;
130      this.value = value;
131      this.comment = comment;
132      this.preLines = preLines;
133      this.modifiers = modifiers;
134   }
135
136   /**
137    * Returns the entry comment.
138    *
139    * @return The entry comment.
140    */
141   public String getComment() { return comment; }
142
143   /**
144    * Returns the configuration name.
145    *
146    * @return The configuration name.
147    */
148   public String getConfig() { return config; }
149
150   /**
151    * Returns the entry name.
152    *
153    * @return The entry name.
154    */
155   public String getKey() { return key; }
156
157   /**
158    * Returns the modifiers on this entry.
159    *
160    * @return
161    *    The modifier characters.
162    *    <br>Never <jk>null</jk>.
163    */
164   public String getModifiers() { return modifiers; }
165
166   /**
167    * Returns the section or entry lines.
168    *
169    * @return The section or entry lines.
170    */
171   public List<String> getPreLines() { return preLines; }
172
173   /**
174    * Returns the section name.
175    *
176    * @return The section name.
177    */
178   public String getSection() { return section; }
179
180   /**
181    * Returns the event type.
182    *
183    * @return The event type.
184    */
185   public ConfigEventType getType() { return type; }
186
187   /**
188    * Returns the entry value.
189    *
190    * @return The entry value.
191    */
192   public String getValue() { return value; }
193
194   @Override /* Overridden from Object */
195   public String toString() {
196      return switch (type) {
197         case REMOVE_SECTION -> "REMOVE_SECTION(" + section + ")";
198         case REMOVE_ENTRY -> "REMOVE_ENTRY(" + section + (section.isEmpty() ? "" : "/") + key + ")";
199         case SET_SECTION -> "SET_SECTION(" + section + ", preLines=" + join(preLines, '|') + ")";
200         case SET_ENTRY -> {
201            var out = new StringBuilder("SET(");
202            out.append(section + (section.isEmpty() ? "" : "/") + key);
203            if (nn(modifiers))
204               out.append(modifiers);
205            out.append(" = ");
206            var val = value == null ? "null" : value;
207            if (val.indexOf('\n') != -1)
208               val = val.replaceAll("(\\r?\\n)", "$1\t");
209            if (val.indexOf('#') != -1)
210               val = val.replace("#", "\\#");
211            out.append(val);
212            if (ne(comment))
213               out.append(" # ").append(comment);
214            out.append(')');
215            yield out.toString();
216         }
217         default -> null; // NOSONAR - Intentional.
218      };
219   }
220}