View Javadoc
1   /*
2    * Themis: Java Project Framework
3    * Copyright 2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  
18  package io.github.tonywasher.joceanus.themis.parser.proj;
19  
20  import io.github.tonywasher.joceanus.themis.parser.base.ThemisChar;
21  import org.w3c.dom.Element;
22  
23  import java.io.File;
24  import java.util.Objects;
25  
26  /**
27   * Maven Module Id.
28   */
29  public final class ThemisMavenId {
30      /**
31       * ElementParser.
32       */
33      interface ThemisElementParser {
34          /**
35           * Obtain element value.
36           *
37           * @param pElement the element
38           * @param pValue   the value name
39           * @return the value
40           */
41          String getElementValue(Element pElement,
42                                 String pValue);
43      }
44  
45      /**
46       * GroupId element.
47       */
48      private static final String EL_GROUPID = "groupId";
49  
50      /**
51       * ArtifactId element.
52       */
53      private static final String EL_ARTIFACTID = "artifactId";
54  
55      /**
56       * Version element.
57       */
58      private static final String EL_VERSION = "version";
59  
60      /**
61       * Scope element.
62       */
63      private static final String EL_SCOPE = "scope";
64  
65      /**
66       * Classifier element.
67       */
68      private static final String EL_CLASSIFIER = "classifier";
69  
70      /**
71       * Optional element.
72       */
73      private static final String EL_OPTIONAL = "optional";
74  
75      /**
76       * The artifactId.
77       */
78      private final String theArtifactId;
79  
80      /**
81       * The groupId.
82       */
83      private String theGroupId;
84  
85      /**
86       * The version.
87       */
88      private String theVersion;
89  
90      /**
91       * The scope.
92       */
93      private final String theScope;
94  
95      /**
96       * The classifier.
97       */
98      private final String theClassifier;
99  
100     /**
101      * Optional.
102      */
103     private final String isOptional;
104 
105     /**
106      * Constructor.
107      *
108      * @param pParser  the parser
109      * @param pElement the element containing the values
110      */
111     ThemisMavenId(final ThemisElementParser pParser,
112                   final Element pElement) {
113         /* Access the values */
114         theGroupId = pParser.getElementValue(pElement, EL_GROUPID);
115         theArtifactId = pParser.getElementValue(pElement, EL_ARTIFACTID);
116         theVersion = pParser.getElementValue(pElement, EL_VERSION);
117         theScope = pParser.getElementValue(pElement, EL_SCOPE);
118         theClassifier = pParser.getElementValue(pElement, EL_CLASSIFIER);
119         isOptional = pParser.getElementValue(pElement, EL_OPTIONAL);
120     }
121 
122     /**
123      * Constructor.
124      *
125      * @param pParser  the parser
126      * @param pElement the element containing the values
127      * @param pParent  the parentId
128      */
129     ThemisMavenId(final ThemisElementParser pParser,
130                   final Element pElement,
131                   final ThemisMavenId pParent) {
132         /* Process as much as we can */
133         this(pParser, pElement);
134 
135         /* Handle missing groupId/version */
136         if (theGroupId == null) {
137             theGroupId = pParent.getGroupId();
138         }
139         if (theVersion == null) {
140             theVersion = pParent.getVersion();
141         }
142 
143         /* If we have a ranged version, set to null */
144         if (theVersion != null
145                 && theVersion.startsWith(String.valueOf(ThemisChar.ARRAY_OPEN))) {
146             theVersion = null;
147         }
148     }
149 
150     /**
151      * Obtain the groupId.
152      *
153      * @return the groupId
154      */
155     public String getGroupId() {
156         return theGroupId;
157     }
158 
159     /**
160      * Obtain the artifactId.
161      *
162      * @return the artifactId
163      */
164     public String getArtifactId() {
165         return theArtifactId;
166     }
167 
168     /**
169      * Obtain the version.
170      *
171      * @return the version
172      */
173     public String getVersion() {
174         return theVersion;
175     }
176 
177     /**
178      * Obtain the scope.
179      *
180      * @return the scope
181      */
182     public String getScope() {
183         return theScope;
184     }
185 
186     /**
187      * Obtain the classifier.
188      *
189      * @return the classifier
190      */
191     public String getClassifier() {
192         return theClassifier;
193     }
194 
195     /**
196      * Obtain the optional.
197      *
198      * @return the optional
199      */
200     public String isOptional() {
201         return isOptional;
202     }
203 
204     /**
205      * is the dependency skippable?
206      *
207      * @return true/false
208      */
209     public boolean isSkippable() {
210         return "test".equals(theScope)
211                 || "runtime".equals(theScope)
212                 || "provided".equals(theScope)
213                 //|| theVersion == null
214                 || isOptional != null;
215     }
216 
217     @Override
218     public boolean equals(final Object pThat) {
219         /* Handle the trivial cases */
220         if (this == pThat) {
221             return true;
222         }
223         if (pThat == null) {
224             return false;
225         }
226 
227         /* Make sure that the object is a MavenId */
228         if (!(pThat instanceof ThemisMavenId myThat)) {
229             return false;
230         }
231 
232         /* Check components */
233         return Objects.equals(theGroupId, myThat.getGroupId())
234                 && Objects.equals(theArtifactId, myThat.getArtifactId())
235                 && Objects.equals(theVersion, myThat.getVersion())
236                 && Objects.equals(theScope, myThat.getScope())
237                 && Objects.equals(theClassifier, myThat.getClassifier());
238     }
239 
240     @Override
241     public int hashCode() {
242         return Objects.hash(theGroupId, theArtifactId, theVersion, theScope, theClassifier);
243     }
244 
245     @Override
246     public String toString() {
247         final String myName = theGroupId + ThemisChar.COLON + theArtifactId + ThemisChar.COLON + theVersion;
248         return theClassifier == null ? myName : myName + ThemisChar.COLON + theClassifier;
249     }
250 
251     /**
252      * Obtain the mavenBase.
253      *
254      * @return the mavenBase path
255      */
256     private File getMavenBasePath() {
257         /* Determine the repository base */
258         File myBase = getMavenCorePath();
259         if (theVersion == null) {
260             getLatestVersion();
261         }
262         myBase = new File(myBase, theVersion);
263         return myBase;
264     }
265 
266     /**
267      * Obtain the latest version for an artifact.
268      */
269     private void getLatestVersion() {
270         final File myBase = getMavenCorePath();
271         ThemisMavenVersion myLatest = null;
272         for (File myFile : Objects.requireNonNull(myBase.listFiles())) {
273             if (myFile.isDirectory()) {
274                 final ThemisMavenVersion myVersion = ThemisMavenVersion.parseVersion(myFile.getName());
275                 if (myVersion != null) {
276                     if (myLatest == null
277                             || myLatest.compareTo(myVersion) < 0) {
278                         myLatest = myVersion;
279                     }
280                 }
281             }
282         }
283         if (myLatest != null) {
284             theVersion = myLatest.getVersion();
285         }
286     }
287 
288     /**
289      * Obtain the mavenBase.
290      *
291      * @return the mavenBase path
292      */
293     private File getMavenCorePath() {
294         /* Determine the repository base */
295         File myBase = new File(System.getProperty("user.home"));
296         myBase = new File(myBase, ".m2");
297         myBase = new File(myBase, "repository");
298         myBase = new File(myBase, theGroupId.replace(ThemisChar.PERIOD, ThemisChar.COMMENT));
299         myBase = new File(myBase, theArtifactId);
300         return myBase;
301     }
302 
303     /**
304      * Obtain the mavenJar.
305      *
306      * @return the mavenJar path
307      */
308     public File getMavenJarPath() {
309         /* Determine the repository base */
310         File myBase = getMavenBasePath();
311         String myName = theArtifactId + ThemisChar.HYPHEN + theVersion;
312         if (theClassifier != null) {
313             myName += ThemisChar.HYPHEN + theClassifier;
314         }
315         myBase = new File(myBase, myName + ".jar");
316         return myBase;
317     }
318 
319     /**
320      * Obtain the mavenJar.
321      *
322      * @return the mavenJar path
323      */
324     public File getMavenPomPath() {
325         /* Determine the repository base */
326         File myBase = getMavenBasePath();
327         myBase = new File(myBase, theArtifactId + ThemisChar.HYPHEN + theVersion + ".pom");
328         return myBase;
329     }
330 }
331