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.lethe.analysis;
18
19 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20 import io.github.tonywasher.joceanus.themis.exc.ThemisIOException;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 /**
30 * Project.
31 */
32 public class ThemisAnalysisProject
33 implements ThemisAnalysisElement {
34 /**
35 * Consolidation Pass error.
36 */
37 private static final String CONSOLIDATION_ERROR = "Failed on consolidation Pass";
38
39 /**
40 * The project name.
41 */
42 private final String theName;
43
44 /**
45 * The location.
46 */
47 private final File theLocation;
48
49 /**
50 * The module list.
51 */
52 private final List<ThemisAnalysisModule> theModules;
53
54 /**
55 * The initial dataMap.
56 */
57 private final ThemisAnalysisDataMap theDataMap;
58
59 /**
60 * The error.
61 */
62 private OceanusException theError;
63
64 /**
65 * Constructor.
66 *
67 * @param pLocation the project location
68 */
69 public ThemisAnalysisProject(final File pLocation) {
70 /* Store the name and location */
71 theLocation = pLocation;
72
73 /* Create the list */
74 theModules = new ArrayList<>();
75
76 /* Create the dataMap */
77 theDataMap = new ThemisAnalysisDataMap();
78
79 /* Initiate search for modules */
80 final ThemisAnalysisMavenId myId = parseProjectFile(new File(theLocation, ThemisAnalysisMaven.POM));
81 theName = myId == null ? null : myId.getArtifactId();
82
83 /* InitialPass */
84 if (theError == null) {
85 performInitialPass();
86 }
87
88 /* ConsolidationPass */
89 if (theError == null) {
90 performConsolidationPass();
91 }
92
93 /* FinalPass */
94 if (theError == null) {
95 performFinalPass();
96 }
97 }
98
99 /**
100 * Obtain the name.
101 *
102 * @return the name
103 */
104 public String getName() {
105 return theName;
106 }
107
108 /**
109 * Obtain the location.
110 *
111 * @return the location
112 */
113 File getLocation() {
114 return theLocation;
115 }
116
117 /**
118 * Obtain the error.
119 *
120 * @return the error
121 */
122 public OceanusException getError() {
123 return theError;
124 }
125
126 /**
127 * Obtain the modules.
128 *
129 * @return the modules
130 */
131 public List<ThemisAnalysisModule> getModules() {
132 return theModules;
133 }
134
135 /**
136 * Obtain the dataMap.
137 *
138 * @return the map
139 */
140 ThemisAnalysisDataMap getDataMap() {
141 return theDataMap;
142 }
143
144 @Override
145 public String toString() {
146 return theName;
147 }
148
149 /**
150 * Parse the maven top-level project file.
151 *
152 * @param pPom the project file
153 * @return the mavenId of the project
154 */
155 private ThemisAnalysisMavenId parseProjectFile(final File pPom) {
156 /* If the pom file does not exist, just return */
157 if (!pPom.exists()) {
158 return null;
159 }
160
161 /* Protect against exceptions */
162 try {
163 /* Add module if source directory exists */
164 final File mySrc = new File(pPom.getParent(), ThemisAnalysisModule.PATH_XTRA);
165 if (mySrc.exists()
166 && mySrc.isDirectory()) {
167 /* Add the module to the list */
168 theModules.add(new ThemisAnalysisModule(this, new File(pPom.getParent())));
169 }
170
171 /* Handle exceptions */
172 } catch (OceanusException e) {
173 /* Save Exception */
174 theError = new ThemisIOException(CONSOLIDATION_ERROR, e);
175 return null;
176 }
177
178 /* Protect against exceptions */
179 try (InputStream myInStream = new FileInputStream(pPom)) {
180 /* Parse the Project definition file */
181 final ThemisAnalysisMaven myPom = new ThemisAnalysisMaven(myInStream);
182
183 /* Loop through the modules */
184 for (final String myModuleName : myPom.getModules()) {
185 /* Access module directory */
186 final File myModuleDir = new File(pPom.getParentFile(), myModuleName);
187
188 /* Process the project file */
189 parseProjectFile(new File(myModuleDir, ThemisAnalysisMaven.POM));
190
191 /* Break loop on error */
192 if (theError != null) {
193 break;
194 }
195 }
196
197 return myPom.getMavenId();
198
199 /* Catch exceptions */
200 } catch (IOException
201 | OceanusException e) {
202 /* Save Exception */
203 theError = new ThemisIOException("Failed to parse Project file", e);
204 return null;
205 }
206 }
207
208 /**
209 * initialPass.
210 */
211 private void performInitialPass() {
212 /* Protect against exceptions */
213 try {
214 /* Loop through the modules */
215 for (ThemisAnalysisModule myModule : theModules) {
216 /* Process the module */
217 myModule.performInitialPass();
218 }
219
220 /* Handle exceptions */
221 } catch (OceanusException e) {
222 /* Save Exception */
223 theError = new ThemisIOException(CONSOLIDATION_ERROR, e);
224 }
225 }
226
227 /**
228 * consolidationPass.
229 */
230 private void performConsolidationPass() {
231 /* Protect against exceptions */
232 try {
233 /* Loop through the modules */
234 for (ThemisAnalysisModule myModule : theModules) {
235 /* Process the module */
236 myModule.performConsolidationPass();
237 }
238
239 /* Handle exceptions */
240 } catch (OceanusException e) {
241 /* Save Exception */
242 theError = new ThemisIOException(CONSOLIDATION_ERROR, e);
243 }
244 }
245
246 /**
247 * finalPass.
248 */
249 private void performFinalPass() {
250 /* Protect against exceptions */
251 try {
252 /* Loop through the modules */
253 for (ThemisAnalysisModule myModule : theModules) {
254 /* Process the module */
255 myModule.performFinalPass();
256 }
257
258 /* Handle exceptions */
259 } catch (OceanusException e) {
260 /* Save Exception */
261 theError = new ThemisIOException("Failed on final pass", e);
262 }
263 }
264 }