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.common.utils.Utils.*;
020import static org.apache.juneau.config.event.ConfigEventType.*;
021
022import java.util.*;
023
024import org.apache.juneau.common.utils.*;
025
026/**
027 * Represents a change to a config.
028 */
029public class ConfigEvent {
030
031   private final ConfigEventType type;
032   private final String config, section, key, value, comment;
033   private final List<String> preLines;
034   private final String modifiers;
035
036   /**
037    * Constructor.
038    * @param type - The event type.
039    * @param config - The configuration name.
040    * @param section - The section name.
041    * @param key - The entry name.
042    * @param value - The entry value.
043    * @param modifiers - The entry modifiers.
044    * @param comment - Optional comment string to add on the same line as the entry.
045    * @param preLines - Optional comment lines that occur before this entry.
046    */
047   protected ConfigEvent(ConfigEventType type, String config, String section, String key, String value, String modifiers, String comment, List<String> preLines) {
048      this.type = type;
049      this.config = config;
050      this.section = section;
051      this.key = key;
052      this.value = value;
053      this.comment = comment;
054      this.preLines = preLines;
055      this.modifiers = modifiers;
056   }
057
058   //---------------------------------------------------------------------------------------------
059   // Static
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    * Removes a value from a configuration.
092    *
093    * @param config
094    *    The configuration name.
095    * @param section
096    *    The section name.
097    *    <br>Must not be <jk>null</jk>.
098    * @param key
099    *    The entry name.
100    *    <br>Must not be <jk>null</jk>.
101    * @return
102    *    A new {@link ConfigEvent} object.
103    */
104   public static ConfigEvent removeEntry(String config, String section, String key) {
105      return new ConfigEvent(REMOVE_ENTRY, config, section, key, null, null, null, null);
106   }
107
108   /**
109    * Adds a new empty section to the config.
110    *
111    * @param config
112    *    The configuration name.
113    * @param section
114    *    The section name.
115    * @param prelines
116    *    Comment lines that occur before this section.
117    *    <br>Must not be <jk>null</jk>.
118    * @return
119    *    A new {@link ConfigEvent} object.
120    */
121   public static ConfigEvent setSection(String config, String section, List<String> prelines) {
122      return new ConfigEvent(SET_SECTION, config, section, null, null, null, null, prelines);
123   }
124
125   /**
126    * Removes a section from the config.
127    *
128    * @param config
129    *    The configuration name.
130    * @param section
131    *    The section name.
132    * @return
133    *    A new {@link ConfigEvent} object.
134    */
135   public static ConfigEvent removeSection(String config, String section) {
136      return new ConfigEvent(REMOVE_SECTION, config, section, null, null, null, null, null);
137   }
138
139   //---------------------------------------------------------------------------------------------
140   // Instance
141   //---------------------------------------------------------------------------------------------
142
143   /**
144    * Returns the event type.
145    *
146    * @return The event type.
147    */
148   public ConfigEventType getType() {
149      return type;
150   }
151
152   /**
153    * Returns the configuration name.
154    *
155    * @return The configuration name.
156    */
157   public String getConfig() {
158      return config;
159   }
160
161   /**
162    * Returns the section name.
163    *
164    * @return The section name.
165    */
166   public String getSection() {
167      return section;
168   }
169
170   /**
171    * Returns the entry name.
172    *
173    * @return The entry name.
174    */
175   public String getKey() {
176      return key;
177   }
178
179   /**
180    * Returns the entry value.
181    *
182    * @return The entry value.
183    */
184   public String getValue() {
185      return value;
186   }
187
188   /**
189    * Returns the entry comment.
190    *
191    * @return The entry comment.
192    */
193   public String getComment() {
194      return comment;
195   }
196
197   /**
198    * Returns the section or entry lines.
199    *
200    * @return The section or entry lines.
201    */
202   public List<String> getPreLines() {
203      return preLines;
204   }
205
206   /**
207    * Returns the modifiers on this entry.
208    *
209    * @return
210    *    The modifier characters.
211    *    <br>Never <jk>null</jk>.
212    */
213   public String getModifiers() {
214      return modifiers;
215   }
216
217   @Override /* Object */
218   public String toString() {
219      return switch (type) {
220         case REMOVE_SECTION -> "REMOVE_SECTION(" + section + ")";
221         case REMOVE_ENTRY -> "REMOVE_ENTRY(" + section + (section.isEmpty() ? "" : "/") + key + ")";
222         case SET_SECTION -> "SET_SECTION(" + section + ", preLines=" + Utils.join(preLines, '|') + ")";
223         case SET_ENTRY -> {
224            var out = new StringBuilder("SET(");
225            out.append(section + (section.isEmpty() ? "" : "/") + key);
226            if (modifiers != null)
227               out.append(modifiers);
228            out.append(" = ");
229            var val = value == null ? "null" : value;
230            if (val.indexOf('\n') != -1)
231               val = val.replaceAll("(\\r?\\n)", "$1\t");
232            if (val.indexOf('#') != -1)
233               val = val.replace("#", "\\#");
234            out.append(val);
235            if (isNotEmpty(comment))
236               out.append(" # ").append(comment);
237            out.append(')');
238            yield out.toString();
239         }
240         default -> null; // NOSONAR - Intentional.
241      };
242   }
243}