View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.internal.impl.model.profile;
20  
21  import java.util.List;
22  
23  import org.apache.maven.api.services.InterpolatorException;
24  import org.apache.maven.api.services.ModelBuilderException;
25  import org.apache.maven.api.services.VersionParser;
26  import org.apache.maven.api.services.model.ProfileActivationContext;
27  
28  import static org.apache.maven.internal.impl.model.profile.ConditionParser.toInt;
29  
30  /**
31   * Provides a set of functions for evaluating profile activation conditions.
32   * These functions can be used in profile activation expressions to determine
33   * whether a profile should be activated based on various criteria.
34   */
35  @SuppressWarnings("unused")
36  public class ConditionFunctions {
37      private final ProfileActivationContext context;
38      private final VersionParser versionParser;
39  
40      /**
41       * Constructs a new ConditionFunctions instance.
42       *
43       * @param context The profile activation context
44       * @param versionParser The version parser for comparing versions
45       */
46      public ConditionFunctions(ProfileActivationContext context, VersionParser versionParser) {
47          this.context = context;
48          this.versionParser = versionParser;
49      }
50  
51      /**
52       * Returns the length of the given string.
53       *
54       * @param args A list containing a single string argument
55       * @return The length of the string
56       * @throws IllegalArgumentException if the number of arguments is not exactly one
57       */
58      public Object length(List<Object> args) {
59          if (args.size() != 1) {
60              throw new IllegalArgumentException("length function requires exactly one argument");
61          }
62          String s = ConditionParser.toString(args.get(0));
63          return s.length();
64      }
65  
66      /**
67       * Converts the given string to uppercase.
68       *
69       * @param args A list containing a single string argument
70       * @return The uppercase version of the input string
71       * @throws IllegalArgumentException if the number of arguments is not exactly one
72       */
73      public Object upper(List<Object> args) {
74          if (args.size() != 1) {
75              throw new IllegalArgumentException("upper function requires exactly one argument");
76          }
77          String s = ConditionParser.toString(args.get(0));
78          return s.toUpperCase();
79      }
80  
81      /**
82       * Converts the given string to lowercase.
83       *
84       * @param args A list containing a single string argument
85       * @return The lowercase version of the input string
86       * @throws IllegalArgumentException if the number of arguments is not exactly one
87       */
88      public Object lower(List<Object> args) {
89          if (args.size() != 1) {
90              throw new IllegalArgumentException("lower function requires exactly one argument");
91          }
92          String s = ConditionParser.toString(args.get(0));
93          return s.toLowerCase();
94      }
95  
96      /**
97       * Returns a substring of the given string.
98       *
99       * @param args A list containing 2 or 3 arguments: the string, start index, and optionally end index
100      * @return The substring
101      * @throws IllegalArgumentException if the number of arguments is not 2 or 3
102      */
103     public Object substring(List<Object> args) {
104         if (args.size() < 2 || args.size() > 3) {
105             throw new IllegalArgumentException("substring function requires 2 or 3 arguments");
106         }
107         String s = ConditionParser.toString(args.get(0));
108         int start = toInt(args.get(1));
109         int end = args.size() == 3 ? toInt(args.get(2)) : s.length();
110         return s.substring(start, end);
111     }
112 
113     /**
114      * Finds the index of a substring within a string.
115      *
116      * @param args A list containing two strings: the main string and the substring to find
117      * @return The index of the substring, or -1 if not found
118      * @throws IllegalArgumentException if the number of arguments is not exactly two
119      */
120     public Object indexOf(List<Object> args) {
121         if (args.size() != 2) {
122             throw new IllegalArgumentException("indexOf function requires exactly two arguments");
123         }
124         String s = ConditionParser.toString(args.get(0));
125         String substring = ConditionParser.toString(args.get(1));
126         return s.indexOf(substring);
127     }
128 
129     /**
130      * Checks if a string contains a given substring.
131      *
132      * @param args A list containing two strings: the main string and the substring to check
133      * @return true if the main string contains the substring, false otherwise
134      * @throws IllegalArgumentException if the number of arguments is not exactly two
135      */
136     public Object contains(List<Object> args) {
137         if (args.size() != 2) {
138             throw new IllegalArgumentException("contains function requires exactly two arguments");
139         }
140         String s = ConditionParser.toString(args.get(0));
141         String substring = ConditionParser.toString(args.get(1));
142         return s.contains(substring);
143     }
144 
145     /**
146      * Checks if a string matches a given regular expression.
147      *
148      * @param args A list containing two strings: the string to check and the regex pattern
149      * @return true if the string matches the regex, false otherwise
150      * @throws IllegalArgumentException if the number of arguments is not exactly two
151      */
152     public Object matches(List<Object> args) {
153         if (args.size() != 2) {
154             throw new IllegalArgumentException("matches function requires exactly two arguments");
155         }
156         String s = ConditionParser.toString(args.get(0));
157         String regex = ConditionParser.toString(args.get(1));
158         return s.matches(regex);
159     }
160 
161     /**
162      * Negates a boolean value.
163      *
164      * @param args A list containing a single boolean argument
165      * @return The negation of the input boolean
166      * @throws IllegalArgumentException if the number of arguments is not exactly one
167      */
168     public Object not(List<Object> args) {
169         if (args.size() != 1) {
170             throw new IllegalArgumentException("not function requires exactly one argument");
171         }
172         return !ConditionParser.toBoolean(args.get(0));
173     }
174 
175     /**
176      * Implements an if-then-else operation.
177      *
178      * @param args A list containing three arguments: condition, value if true, value if false
179      * @return The second argument if the condition is true, the third argument otherwise
180      * @throws IllegalArgumentException if the number of arguments is not exactly three
181      */
182     @SuppressWarnings("checkstyle:MethodName")
183     public Object if_(List<Object> args) {
184         if (args.size() != 3) {
185             throw new IllegalArgumentException("if function requires exactly three arguments");
186         }
187         boolean condition = ConditionParser.toBoolean(args.get(0));
188         return condition ? args.get(1) : args.get(2);
189     }
190 
191     /**
192      * Checks if a file or directory exists at the given path.
193      *
194      * @param args A list containing a single string argument representing the path
195      * @return {@code true} if the file or directory exists, {@code false} otherwise
196      * @throws IllegalArgumentException if the number of arguments is not exactly one
197      * @throws ModelBuilderException if a problem occurs while walking the file system
198      * @throws InterpolatorException if an error occurs during interpolation
199      */
200     public Object exists(List<Object> args) {
201         if (args.size() != 1) {
202             throw new IllegalArgumentException("exists function requires exactly one argument");
203         }
204         String path = ConditionParser.toString(args.get(0));
205         return context.exists(path, true);
206     }
207 
208     /**
209      * Checks if a file or directory is missing at the given path.
210      *
211      * @param args A list containing a single string argument representing the path
212      * @return {@code true} if the file or directory does not exist, {@code false} otherwise
213      * @throws IllegalArgumentException if the number of arguments is not exactly one
214      * @throws ModelBuilderException if a problem occurs while walking the file system
215      * @throws InterpolatorException if an error occurs during interpolation
216      */
217     public Object missing(List<Object> args) {
218         if (args.size() != 1) {
219             throw new IllegalArgumentException("missing function requires exactly one argument");
220         }
221         String path = ConditionParser.toString(args.get(0));
222         return !context.exists(path, true);
223     }
224 
225     /**
226      * Checks if a version is within a specified version range.
227      *
228      * @param args A list containing two strings: the version to check and the version range
229      * @return true if the version is within the range, false otherwise
230      * @throws IllegalArgumentException if the number of arguments is not exactly two
231      */
232     public Object inrange(List<Object> args) {
233         if (args.size() != 2) {
234             throw new IllegalArgumentException("inrange function requires exactly two arguments");
235         }
236         String version = ConditionParser.toString(args.get(0));
237         String range = ConditionParser.toString(args.get(1));
238         return versionParser.parseVersionRange(range).contains(versionParser.parseVersion(version));
239     }
240 }