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);
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);
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 prelines
079    *    Comment lines that occur before this entry.
080    *    <br>Must not be <jk>null</jk>.
081    * @return
082    *    A new {@link ConfigEvent} object.
083    */
084   public static ConfigEvent setEntry(String config, String section, String key, String value, String comment, List<String> prelines) {
085      return new ConfigEvent(SET_ENTRY, config, section, key, value, comment, prelines);
086   }
087
088   /**
089    * Adds a new empty section to the config.
090    *
091    * @param config
092    *    The configuration name.
093    * @param section
094    *    The section name.
095    * @param prelines
096    *    Comment lines that occur before this section.
097    *    <br>Must not be <jk>null</jk>.
098    * @return
099    *    A new {@link ConfigEvent} object.
100    */
101   public static ConfigEvent setSection(String config, String section, List<String> prelines) {
102      return new ConfigEvent(SET_SECTION, config, section, null, null, null, prelines);
103   }
104
105   private final ConfigEventType type;
106   private final String config;
107   private final String section;
108   private final String key;
109   private final String value;
110   private final String comment;
111
112   private final List<String> preLines;
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 comment - Optional comment string to add on the same line as the entry.
122    * @param preLines - Optional comment lines that occur before this entry.
123    */
124   @SuppressWarnings({
125      "java:S107" // Constructor requires 7 parameters for configuration event
126   })
127   protected ConfigEvent(ConfigEventType type, String config, String section, String key, String value, String comment, List<String> preLines) {
128      this.type = type;
129      this.config = config;
130      this.section = section;
131      this.key = key;
132      this.value = value;
133      this.comment = comment;
134      this.preLines = u(cp(preLines));
135   }
136
137   /**
138    * Returns the entry comment.
139    *
140    * @return The entry comment.
141    */
142   public String getComment() { return comment; }
143
144   /**
145    * Returns the configuration name.
146    *
147    * @return The configuration name.
148    */
149   public String getConfig() { return config; }
150
151   /**
152    * Returns the entry name.
153    *
154    * @return The entry name.
155    */
156   public String getKey() { return key; }
157
158   /**
159    * Returns the section or entry lines.
160    *
161    * @return An unmodifiable list of the section or entry lines, or <jk>null</jk> if none were supplied.
162    */
163   public List<String> getPreLines() { return preLines; }
164
165   /**
166    * Returns the section name.
167    *
168    * @return The section name.
169    */
170   public String getSection() { return section; }
171
172   /**
173    * Returns the event type.
174    *
175    * @return The event type.
176    */
177   public ConfigEventType getType() { return type; }
178
179   /**
180    * Returns the entry value.
181    *
182    * @return The entry value.
183    */
184   public String getValue() { return value; }
185
186   @Override /* Overridden from Object */
187   public String toString() {
188      return switch (type) {
189         case REMOVE_SECTION -> "REMOVE_SECTION(" + section + ")";
190         case REMOVE_ENTRY -> "REMOVE_ENTRY(" + section + (section.isEmpty() ? "" : "/") + key + ")";
191         case SET_SECTION -> "SET_SECTION(" + section + ", preLines=" + join(preLines, '|') + ")";
192         case SET_ENTRY -> {
193            var out = new StringBuilder("SET(");
194            out.append(section + (section.isEmpty() ? "" : "/") + key);
195            out.append(" = ");
196            var val = value == null ? "null" : value;
197            if (val.indexOf('\n') != -1)
198               val = val.replaceAll("(\\r?\\n)", "$1\t");
199            if (val.indexOf('#') != -1)
200               val = val.replace("#", "\\#");
201            out.append(val);
202            if (ine(comment))
203               out.append(" # ").append(comment);
204            out.append(')');
205            yield out.toString();
206         }
207         default -> null;
208      };
209   }
210}