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.exc.ThemisDataException;
21  import io.github.tonywasher.joceanus.themis.lethe.analysis.ThemisAnalysisFile.ThemisAnalysisObject;
22  
23  import java.util.ArrayDeque;
24  import java.util.Collections;
25  import java.util.Deque;
26  import java.util.Iterator;
27  
28  /**
29   * Interface for containers that require postProcessing.
30   */
31  public interface ThemisAnalysisContainer
32          extends ThemisAnalysisProcessed {
33      /**
34       * Adoptable interface.
35       */
36      interface ThemisAnalysisAdoptable {
37          /**
38           * Set the parent of this container.
39           *
40           * @param pParent the parent
41           */
42          void setParent(ThemisAnalysisContainer pParent);
43      }
44  
45      /**
46       * Obtain the dataMap.
47       *
48       * @return the map
49       */
50      default ThemisAnalysisDataMap getDataMap() {
51          return getParent().getDataMap();
52      }
53  
54      /**
55       * Obtain the contents.
56       *
57       * @return the contents
58       */
59      Deque<ThemisAnalysisElement> getContents();
60  
61      /**
62       * Obtain the parent of this container.
63       *
64       * @return the parent
65       */
66      ThemisAnalysisContainer getParent();
67  
68      /**
69       * Determine the full name of the child object.
70       *
71       * @param pChildName the child name
72       * @return the fullName
73       */
74      default String determineFullChildName(final String pChildName) {
75          /* Loop */
76          ThemisAnalysisContainer myContainer = this;
77          while (true) {
78              if (myContainer instanceof ThemisAnalysisObject myObject) {
79                  return myObject.getFullName() + ThemisAnalysisChar.PERIOD + pChildName;
80              }
81              if (myContainer instanceof ThemisAnalysisFile myFile) {
82                  return myFile.getPackageName() + ThemisAnalysisChar.PERIOD + pChildName;
83              }
84              myContainer = myContainer.getParent();
85          }
86      }
87  
88      /**
89       * Post process lines.
90       *
91       * @throws OceanusException on error
92       */
93      default void postProcessLines() throws OceanusException {
94          /* Create a copy of the contents list and clear original */
95          final Deque<ThemisAnalysisElement> myContents = getContents();
96          final Deque<ThemisAnalysisElement> myLines = new ArrayDeque<>(myContents);
97          myContents.clear();
98  
99          /* Create the new input parser */
100         final ThemisAnalysisParser myParser = new ThemisAnalysisParser(myLines, myContents, getParent());
101 
102         /* Loop through the lines */
103         while (myParser.hasLines()) {
104             /* Access next line */
105             final ThemisAnalysisElement myElement = myParser.popNextLine();
106 
107             /* If the element is an embedded block */
108             if (myElement instanceof ThemisAnalysisEmbedded myEmbedded) {
109                 /* Access and process the block */
110                 final ThemisAnalysisElement myResult = myParser.processEmbedded(myEmbedded);
111                 myContents.add(myResult);
112 
113                 /* If the element is a methodBody */
114             } else if (myElement instanceof ThemisAnalysisMethodBody myMethod) {
115                 /* Access and process the block */
116                 final ThemisAnalysisElement myResult = myParser.processMethodBody(myMethod);
117                 myContents.add(myResult);
118 
119                 /* If the element is a container */
120             } else if (myElement instanceof ThemisAnalysisContainer myContainer) {
121                 /* Access and process the container */
122                 myContainer.postProcessLines();
123                 myContents.add(myContainer);
124 
125                 /* If the element is already fully processed */
126             } else if (myElement instanceof ThemisAnalysisProcessed) {
127                 myContents.add(myElement);
128 
129                 /* process lines */
130             } else if (myElement instanceof ThemisAnalysisLine myLine) {
131                 final ThemisAnalysisElement myResult = myParser.processFieldsAndMethods(myLine);
132 
133                 /* If we have a field/method */
134                 if (myResult != null) {
135                     /* Add the element and postProcess any Containers */
136                     myContents.add(myResult);
137 
138                     /* else */
139                 } else {
140                     /* Process statement */
141                     myContents.add(myParser.processStatement(myLine));
142                 }
143 
144                 /* Everything should now be a line. */
145             } else {
146                 throw new ThemisDataException("Unexpected dataType");
147             }
148         }
149 
150         /* Process extras */
151         postProcessExtras();
152     }
153 
154     /**
155      * Post process extra lines.
156      *
157      * @throws OceanusException on error
158      */
159     default void postProcessExtras() throws OceanusException {
160         /* NoOp by default */
161     }
162 
163     /**
164      * Obtain iterator for chained containers.
165      *
166      * @return the iterator
167      */
168     default Iterator<ThemisAnalysisContainer> containerIterator() {
169         return Collections.emptyIterator();
170     }
171 }