001/*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014
015package org.basepom.mojo.propertyhelper.definitions;
016
017import static com.google.common.base.Preconditions.checkState;
018
019import org.basepom.mojo.propertyhelper.Field;
020import org.basepom.mojo.propertyhelper.FieldContext;
021import org.basepom.mojo.propertyhelper.IgnoreWarnFail;
022import org.basepom.mojo.propertyhelper.IgnoreWarnFailCreate;
023import org.basepom.mojo.propertyhelper.ValueCache;
024
025import java.io.File;
026import java.io.IOException;
027import java.util.List;
028import java.util.Objects;
029import java.util.Optional;
030import java.util.StringJoiner;
031import java.util.function.Function;
032import java.util.regex.Matcher;
033import java.util.regex.Pattern;
034
035import com.google.common.annotations.VisibleForTesting;
036import com.google.common.base.Splitter;
037
038/**
039 * Common properties for a field.
040 */
041public abstract class FieldDefinition<T> {
042
043    protected FieldDefinition() {
044    }
045
046    @VisibleForTesting
047    protected FieldDefinition(String id) {
048        this.id = id;
049    }
050
051    /**
052     * Name of the build property to define. Field injected by Maven.
053     */
054    String id = null;
055
056    /**
057     * <code>True</code> skips the parsing of this definition. Field injected by Maven.
058     */
059    boolean skip = false;
060
061    /**
062     * Whether to export this number directly. Field injected by Maven.
063     */
064    boolean export = false;
065
066    /**
067     * Name of the property from the properties file. Field injected by Maven.
068     */
069    String propertyNameInFile = null;
070
071    /**
072     * Name of the properties file to persist the count. Field injected by Maven.
073     */
074    File propertyFile = null;
075
076    /**
077     * What to do when the property is missing from the file.
078     */
079    private IgnoreWarnFailCreate onMissingFile = IgnoreWarnFailCreate.FAIL;
080
081    public void setOnMissingFile(String onMissingFile) {
082        this.onMissingFile = IgnoreWarnFailCreate.forString(onMissingFile);
083    }
084
085    /**
086     * What to do when the property is missing from the file.
087     */
088    private IgnoreWarnFailCreate onMissingFileProperty = IgnoreWarnFailCreate.FAIL;
089
090    public void setOnMissingFileProperty(String onMissingFileProperty) {
091        this.onMissingFileProperty = IgnoreWarnFailCreate.forString(onMissingFileProperty);
092    }
093
094    /**
095     * What to do when a referenced property can not be resolved.
096     */
097    private IgnoreWarnFail onMissingProperty = IgnoreWarnFail.FAIL;
098
099    public void setOnMissingProperty(String onMissingProperty) {
100        this.onMissingProperty = IgnoreWarnFail.forString(onMissingProperty);
101    }
102
103    /**
104     * The initial value for this field. Field injected by Maven.
105     */
106    String initialValue = null;
107
108    /**
109     * Regular expression matcher. Field injected by Maven.
110     */
111    private Pattern regexp = null;
112
113    public void setRegexp(String regexp) {
114        checkState(regexp.startsWith("^"), "regular expression must start with '^'!");
115        checkState(regexp.endsWith("$"), "regular expression must end with '$'!");
116
117        this.regexp = Pattern.compile(regexp);
118    }
119
120    /**
121     * Format for this element. Field injected by Maven.
122     */
123    String format = null;
124
125    /**
126     * Comma separated list of String transformers.
127     */
128    private List<String> transformers = List.of();
129
130    public void setTransformers(String transformers) {
131        this.transformers = Splitter.on(",")
132            .omitEmptyStrings()
133            .trimResults()
134            .splitToList(transformers);
135    }
136
137    public abstract <U extends Field<?, ?>> U createField(FieldContext context, ValueCache valueCache) throws IOException;
138
139    public String getId() {
140        return id;
141    }
142
143    public boolean isSkip() {
144        return skip;
145    }
146
147    public List<String> getTransformers() {
148        return transformers;
149    }
150
151    public Optional<String> getInitialValue() {
152        return Optional.ofNullable(initialValue);
153    }
154
155    public boolean isExport() {
156        return export;
157    }
158
159    public String getPropertyNameInFile() {
160        return Objects.requireNonNullElse(propertyNameInFile, id);
161    }
162
163    public Optional<File> getPropertyFile() {
164        return Optional.ofNullable(propertyFile);
165    }
166
167    public IgnoreWarnFailCreate getOnMissingFile() {
168        return onMissingFile;
169    }
170
171    public IgnoreWarnFailCreate getOnMissingFileProperty() {
172        return onMissingFileProperty;
173    }
174
175    public IgnoreWarnFail getOnMissingProperty() {
176        return onMissingProperty;
177    }
178
179    public Function<String, String> getRegexp() {
180        return regexp == null ? Function.identity() : v -> {
181            Matcher matcher = regexp.matcher(v);
182            return matcher.matches() ? matcher.group(1) : "";
183        };
184    }
185
186    public Function<T, String> getPreFormat() {
187        return v -> v == null ? "" : String.valueOf(v);
188    }
189
190    public Function<String, String> getPostFormat() {
191        return format == null ? String::valueOf : v -> String.format(format, v);
192    }
193
194    public void check() {
195        checkState(id != null, "the id element must not be empty!");
196
197        if (propertyNameInFile != null) {
198            checkState(propertyFile != null, "can not define <propertyNameInFile> without defining <propertyFile>!");
199        }
200    }
201
202    @Override
203    public String toString() {
204        return new StringJoiner(", ", FieldDefinition.class.getSimpleName() + "[", "]")
205            .add("id='" + id + "'")
206            .add("skip=" + skip)
207            .add("export=" + export)
208            .add("propertyNameInFile='" + propertyNameInFile + "'")
209            .add("propertyFile=" + propertyFile)
210            .add("onMissingFile=" + onMissingFile)
211            .add("onMissingFileProperty=" + onMissingFileProperty)
212            .add("onMissingProperty=" + onMissingProperty)
213            .add("initialValue='" + initialValue + "'")
214            .add("format='" + format + "'")
215            .add("transformers=" + transformers)
216            .toString();
217    }
218
219    @Override
220    public boolean equals(Object o) {
221        if (this == o) {
222            return true;
223        }
224        if (o == null || getClass() != o.getClass()) {
225            return false;
226        }
227        FieldDefinition<?> that = (FieldDefinition<?>) o;
228        return skip == that.skip && export == that.export && Objects.equals(id, that.id) && Objects.equals(propertyNameInFile,
229            that.propertyNameInFile) && Objects.equals(propertyFile, that.propertyFile) && onMissingFile == that.onMissingFile
230            && onMissingFileProperty == that.onMissingFileProperty && onMissingProperty == that.onMissingProperty && Objects.equals(initialValue,
231            that.initialValue) && Objects.equals(format, that.format) && Objects.equals(transformers, that.transformers);
232    }
233
234    @Override
235    public int hashCode() {
236        return Objects.hash(id, skip, export, propertyNameInFile, propertyFile, onMissingFile, onMissingFileProperty, onMissingProperty, initialValue, format,
237            transformers);
238    }
239}