View Javadoc
1   /*
2    * Themis: Java Project Framework
3    * Copyright 2012-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  package io.github.tonywasher.joceanus.themis.xanalysis.parser.proj;
18  
19  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20  import io.github.tonywasher.joceanus.themis.exc.ThemisIOException;
21  import io.github.tonywasher.joceanus.themis.xanalysis.parser.base.ThemisXAnalysisParserDef;
22  import io.github.tonywasher.joceanus.themis.xanalysis.parser.proj.ThemisXAnalysisMaven.ThemisXAnalysisMavenId;
23  
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.util.ArrayList;
29  import java.util.LinkedHashMap;
30  import java.util.List;
31  import java.util.Map;
32  
33  /**
34   * Project.
35   */
36  public class ThemisXAnalysisProject {
37      /**
38       * Consolidation Pass error.
39       */
40      private static final String CONSOLIDATION_ERROR = "Failed on consolidation Pass";
41  
42      /**
43       * The project name.
44       */
45      private final String theName;
46  
47      /**
48       * The location.
49       */
50      private final File theLocation;
51  
52      /**
53       * The module map.
54       */
55      private final Map<ThemisXAnalysisMavenId, ThemisXAnalysisModule> theModules;
56  
57      /**
58       * The dependencies.
59       */
60      private final List<ThemisXAnalysisMavenId> theDependencies;
61  
62      /**
63       * Constructor.
64       *
65       * @param pLocation the project location
66       * @throws OceanusException on error
67       */
68      public ThemisXAnalysisProject(final File pLocation) throws OceanusException {
69          /* Store the name and location */
70          theLocation = pLocation;
71  
72          /* Create the list */
73          theModules = new LinkedHashMap<>();
74          theDependencies = new ArrayList<>();
75  
76          /* Initiate search for modules */
77          final ThemisXAnalysisMaven myPom = parseProjectFile(null, new File(theLocation, ThemisXAnalysisMaven.POM));
78          theName = myPom == null ? null : myPom.getMavenId().getArtifactId();
79  
80          /* Remove own mavenIds from dependency list */
81          theDependencies.removeIf(theModules::containsKey);
82  
83          /* For all dependencies */
84          final List<ThemisXAnalysisMavenId> myDependencies = new ArrayList<>(theDependencies);
85          for (ThemisXAnalysisMavenId myId : myDependencies) {
86              processDependency(myId);
87          }
88      }
89  
90      /**
91       * Process dependency.
92       *
93       * @param pId the maven id
94       */
95      private void processDependency(final ThemisXAnalysisMavenId pId) throws OceanusException {
96          final File myFile = pId.getMavenPomPath();
97          /* Protect against exceptions */
98          try (InputStream myInStream = new FileInputStream(myFile)) {
99              /* Parse the Project definition file */
100             final ThemisXAnalysisMaven myPom = new ThemisXAnalysisMaven(null, myInStream);
101 
102             /* Add any unique dependencies */
103             for (final ThemisXAnalysisMavenId myDepId : myPom.getDependencies()) {
104                 if (!theDependencies.contains(myDepId)) {
105                     theDependencies.add(myDepId);
106                     if (myDepId.getClassifier() == null) {
107                         processDependency(myDepId);
108                     }
109                 }
110             }
111         } catch (IOException e) {
112             throw new ThemisIOException("Failed to parse pom file", e);
113         }
114     }
115 
116     /**
117      * Obtain the name.
118      *
119      * @return the name
120      */
121     public String getName() {
122         return theName;
123     }
124 
125     /**
126      * Obtain the location.
127      *
128      * @return the location
129      */
130     File getLocation() {
131         return theLocation;
132     }
133 
134     /**
135      * Obtain the modules.
136      *
137      * @return the modules
138      */
139     public List<ThemisXAnalysisModule> getModules() {
140         return new ArrayList<>(theModules.values());
141     }
142 
143     /**
144      * Obtain the dependencies.
145      *
146      * @return the dependencies
147      */
148     public List<ThemisXAnalysisMavenId> getDependencies() {
149         return theDependencies;
150     }
151 
152     @Override
153     public String toString() {
154         return theName;
155     }
156 
157     /**
158      * Parse the maven project file.
159      *
160      * @param pParent the parent
161      * @param pPom    the project file
162      * @return the artifact name
163      * @throws OceanusException on error
164      */
165     private ThemisXAnalysisMaven parseProjectFile(final ThemisXAnalysisMaven pParent,
166                                                   final File pPom) throws OceanusException {
167         /* If the pom file does not exist, just return */
168         if (!pPom.exists()) {
169             return null;
170         }
171 
172         /* Protect against exceptions */
173         try (InputStream myInStream = new FileInputStream(pPom)) {
174             /* Parse the Project definition file */
175             final ThemisXAnalysisMaven myPom = new ThemisXAnalysisMaven(pParent, myInStream);
176 
177             /* If source directory exists */
178             final File mySrc = new File(pPom.getParent(), ThemisXAnalysisModule.PATH_XTRA);
179             if (mySrc.exists()
180                     && mySrc.isDirectory()) {
181                 /* Add the module to the list */
182                 theModules.put(myPom.getMavenId(), new ThemisXAnalysisModule(new File(pPom.getParent()), myPom));
183 
184                 /* Add any unique dependencies */
185                 for (final ThemisXAnalysisMavenId myDepId : myPom.getDependencies()) {
186                     if (!theDependencies.contains(myDepId)) {
187                         theDependencies.add(myDepId);
188                     }
189                 }
190             }
191 
192             /* Loop through the modules */
193             for (final String myModuleName : myPom.getModules()) {
194                 /* Access module directory */
195                 final File myModuleDir = new File(pPom.getParentFile(), myModuleName);
196 
197                 /* Process the project file */
198                 parseProjectFile(myPom, new File(myModuleDir, ThemisXAnalysisMaven.POM));
199             }
200 
201             /* Return the POM */
202             return myPom;
203 
204             /* Catch exceptions */
205         } catch (IOException e) {
206             /* Convert Exception */
207             throw new ThemisIOException("Failed to parse Project file", e);
208         }
209     }
210 
211     /**
212      * parse the java code.
213      *
214      * @param pParser the parser
215      * @throws OceanusException on error
216      */
217     public void parseJavaCode(final ThemisXAnalysisParserDef pParser) throws OceanusException {
218         /* Loop through the modules */
219         for (ThemisXAnalysisModule myModule : theModules.values()) {
220             /* Process the module */
221             myModule.parseJavaCode(pParser);
222         }
223     }
224 }