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.lethe.analysis;
18  
19  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20  import io.github.tonywasher.joceanus.themis.lethe.analysis.ThemisAnalysisContainer.ThemisAnalysisAdoptable;
21  import io.github.tonywasher.joceanus.themis.lethe.analysis.ThemisAnalysisIf.ThemisIteratorChain;
22  import io.github.tonywasher.joceanus.themis.lethe.analysis.ThemisAnalysisStatement.ThemisAnalysisStatementHolder;
23  
24  import java.util.ArrayDeque;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.Deque;
28  import java.util.Iterator;
29  import java.util.List;
30  
31  /**
32   * Try construct.
33   */
34  public class ThemisAnalysisTry
35          implements ThemisAnalysisContainer, ThemisAnalysisAdoptable, ThemisAnalysisStatementHolder {
36      /**
37       * The contents.
38       */
39      private final Deque<ThemisAnalysisElement> theContents;
40  
41      /**
42       * The catch clause(s).
43       */
44      private final ThemisAnalysisCatch theCatch;
45  
46      /**
47       * The finally clause.
48       */
49      private final ThemisAnalysisFinally theFinally;
50  
51      /**
52       * The headers.
53       */
54      private final ThemisAnalysisStack theHeaders;
55  
56      /**
57       * The fields.
58       */
59      private final List<ThemisAnalysisField> theFields;
60  
61      /**
62       * The number of lines.
63       */
64      private final int theNumLines;
65  
66      /**
67       * The dataMap.
68       */
69      private final ThemisAnalysisDataMap theDataMap;
70  
71      /**
72       * The parent.
73       */
74      private ThemisAnalysisContainer theParent;
75  
76      /**
77       * Constructor.
78       *
79       * @param pParser the parser
80       * @param pLine   the initial try line
81       * @throws OceanusException on error
82       */
83      ThemisAnalysisTry(final ThemisAnalysisParser pParser,
84                        final ThemisAnalysisLine pLine) throws OceanusException {
85          /* Access details from parser */
86          theParent = pParser.getParent();
87          theDataMap = new ThemisAnalysisDataMap(theParent.getDataMap());
88  
89          /* Create the arrays */
90          final Deque<ThemisAnalysisElement> myHeaders = ThemisAnalysisBuilder.parseHeaders(pParser, pLine);
91          final Deque<ThemisAnalysisElement> myLines = ThemisAnalysisBuilder.processBody(pParser);
92          theNumLines = myHeaders.size() + 1;
93  
94          /* Look for catch clauses */
95          theCatch = (ThemisAnalysisCatch) pParser.processExtra(this, ThemisAnalysisKeyWord.CATCH);
96  
97          /* Look for finally clauses */
98          theFinally = (ThemisAnalysisFinally) pParser.processExtra(this, ThemisAnalysisKeyWord.FINALLY);
99  
100         /* Create a parser */
101         theContents = new ArrayDeque<>();
102         final ThemisAnalysisParser myParser = new ThemisAnalysisParser(myLines, theContents, this);
103         myParser.processLines();
104 
105         /* Parse the headers */
106         theFields = new ArrayList<>();
107         theHeaders = new ThemisAnalysisStack(myHeaders);
108     }
109 
110     @Override
111     public Deque<ThemisAnalysisElement> getContents() {
112         return theContents;
113     }
114 
115     @Override
116     public void postProcessExtras() throws OceanusException {
117         /* Process the catch clause if required */
118         if (theCatch != null) {
119             theCatch.postProcessLines();
120         }
121 
122         /* Process the finally clause if required */
123         if (theFinally != null) {
124             theFinally.postProcessLines();
125         }
126 
127         /* If the headers are non empty */
128         if (!theHeaders.isEmpty()) {
129             /* Strip out parentheses and create scanner */
130             final ThemisAnalysisStack myResources = theHeaders.extractParentheses();
131             final ThemisAnalysisScanner myScanner = new ThemisAnalysisScanner(myResources);
132 
133             /* Create field for each resource */
134             while (myResources.hasLines()) {
135                 final Deque<ThemisAnalysisElement> myResource = myScanner.scanForSeparator(ThemisAnalysisChar.SEMICOLON);
136                 theFields.add(new ThemisAnalysisField(getDataMap(), new ThemisAnalysisStack(myResource)));
137             }
138         }
139     }
140 
141     @Override
142     public ThemisAnalysisContainer getParent() {
143         return theParent;
144     }
145 
146     @Override
147     public void setParent(final ThemisAnalysisContainer pParent) {
148         theParent = pParent;
149         theDataMap.setParent(pParent.getDataMap());
150         if (theCatch != null) {
151             theCatch.setParent(pParent);
152         }
153         if (theFinally != null) {
154             theFinally.setParent(pParent);
155         }
156     }
157 
158     @Override
159     public ThemisAnalysisDataMap getDataMap() {
160         return theDataMap;
161     }
162 
163     /**
164      * Obtain the additional catch clause (if any).
165      *
166      * @return the catch clause
167      */
168     public ThemisAnalysisCatch getCatch() {
169         return theCatch;
170     }
171 
172     /**
173      * Obtain the additional finally clause (if any).
174      *
175      * @return the finally clause
176      */
177     public ThemisAnalysisFinally getFinally() {
178         return theFinally;
179     }
180 
181     @Override
182     public int getNumLines() {
183         return theNumLines;
184     }
185 
186     @Override
187     public Iterator<ThemisAnalysisStatement> statementIterator() {
188         return ThemisAnalysisField.statementIteratorForFields(theFields);
189     }
190 
191     @Override
192     public Iterator<ThemisAnalysisContainer> containerIterator() {
193         final Iterator<ThemisAnalysisContainer> myCatch = theCatch == null
194                 ? Collections.emptyIterator()
195                 : Collections.singleton((ThemisAnalysisContainer) theCatch).iterator();
196         final Iterator<ThemisAnalysisContainer> myFinally = theFinally == null
197                 ? Collections.emptyIterator()
198                 : Collections.singleton((ThemisAnalysisContainer) theFinally).iterator();
199         return new ThemisIteratorChain<>(myCatch, myFinally);
200     }
201 
202     @Override
203     public String toString() {
204         /* Start parameters */
205         final StringBuilder myBuilder = new StringBuilder();
206 
207         /* Build parameters */
208         boolean bFirst = true;
209         for (ThemisAnalysisField myField : theFields) {
210             /* Handle separators */
211             if (!bFirst) {
212                 myBuilder.append(ThemisAnalysisChar.LF);
213             } else {
214                 bFirst = false;
215             }
216 
217             /* Add parameter */
218             myBuilder.append(myField);
219         }
220 
221         /* Return the string */
222         return myBuilder.toString();
223     }
224 }