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.ThemisAnalysisFile.ThemisAnalysisObject;
22  
23  import java.util.ArrayDeque;
24  import java.util.Collections;
25  import java.util.Deque;
26  import java.util.List;
27  
28  /**
29   * Anonymous Class.
30   */
31  public class ThemisAnalysisAnonClass
32          implements ThemisAnalysisObject, ThemisAnalysisAdoptable {
33      /**
34       * The anon sequence.
35       */
36      static final String ANON = "() " + ThemisAnalysisChar.BRACE_OPEN;
37  
38      /**
39       * The diamond sequence.
40       */
41      static final String DIAMOND = "<>";
42  
43      /**
44       * The full name of the class.
45       */
46      private final String theFullName;
47  
48      /**
49       * The base name of the class.
50       */
51      private final String theBaseName;
52  
53      /**
54       * The ancestors.
55       */
56      private final List<ThemisAnalysisReference> theAncestors;
57  
58      /**
59       * The contents.
60       */
61      private final Deque<ThemisAnalysisElement> theContents;
62  
63      /**
64       * The Parent.
65       */
66      private ThemisAnalysisContainer theParent;
67  
68      /**
69       * The dataMap.
70       */
71      private final ThemisAnalysisDataMap theDataMap;
72  
73      /**
74       * Constructor.
75       *
76       * @param pParser the parser
77       * @param pLine   the initial class line
78       * @throws OceanusException on error
79       */
80      ThemisAnalysisAnonClass(final ThemisAnalysisParser pParser,
81                              final ThemisAnalysisLine pLine) throws OceanusException {
82          /* Strip the trailer */
83          pLine.stripEndSequence(ANON);
84  
85          /* Check for diamonds */
86          if (pLine.endsWithSequence(DIAMOND)) {
87              pLine.stripEndSequence(DIAMOND);
88          }
89  
90          /* Access the base of the anonymous class and strip the new keyword */
91          theBaseName = pLine.stripLastToken();
92          pLine.stripEndSequence(ThemisAnalysisKeyWord.NEW.getKeyWord());
93  
94          /* Access parent dataMap */
95          theParent = pParser.getParent();
96          final ThemisAnalysisDataMap myParentDataMap = theParent.getDataMap();
97  
98          /* Determine the full name */
99          final int myId = myParentDataMap.getLocalId("");
100         theFullName = theParent.determineFullChildName(Integer.toString(myId));
101 
102         /* Create local dataMap */
103         theDataMap = new ThemisAnalysisDataMap(myParentDataMap);
104 
105         /* Parse the body */
106         final Deque<ThemisAnalysisElement> myLines = ThemisAnalysisBuilder.processBody(pParser);
107 
108         /* Create a parser */
109         theContents = new ArrayDeque<>();
110         final ThemisAnalysisParser myParser = new ThemisAnalysisParser(myLines, theContents, this);
111 
112         /* Parse the ancestor and lines */
113         final ThemisAnalysisLine myBaseLine = new ThemisAnalysisLine(theBaseName.toCharArray(), 0, theBaseName.length());
114         final ThemisAnalysisReference myAncestor = ThemisAnalysisParser.parseDataType(theDataMap, myBaseLine);
115         theAncestors = Collections.singletonList(myAncestor);
116         myParser.processLines();
117     }
118 
119     @Override
120     public String getShortName() {
121         return toString();
122     }
123 
124     @Override
125     public String getFullName() {
126         return theFullName;
127     }
128 
129     @Override
130     public ThemisAnalysisProperties getProperties() {
131         return null;
132     }
133 
134     @Override
135     public Deque<ThemisAnalysisElement> getContents() {
136         return theContents;
137     }
138 
139     @Override
140     public ThemisAnalysisContainer getParent() {
141         return this;
142     }
143 
144     @Override
145     public void setParent(final ThemisAnalysisContainer pParent) {
146         theParent = pParent;
147         theDataMap.setParent(pParent.getDataMap());
148     }
149 
150     @Override
151     public ThemisAnalysisDataMap getDataMap() {
152         return theDataMap;
153     }
154 
155     @Override
156     public List<ThemisAnalysisReference> getAncestors() {
157         return theAncestors;
158     }
159 
160     @Override
161     public int getNumLines() {
162         return 0;
163     }
164 
165     @Override
166     public String toString() {
167         return ThemisAnalysisKeyWord.NEW.toString() + " " + theBaseName + "()";
168     }
169 
170     /**
171      * Check for anonymous class.
172      *
173      * @param pLine the line to check
174      * @return true/false
175      */
176     static boolean checkAnon(final ThemisAnalysisLine pLine) {
177         /* Check for possible anonymous class */
178         if (!pLine.endsWithSequence(ANON)) {
179             return false;
180         }
181 
182         /* Take a copy of the line and strip the trailer */
183         final ThemisAnalysisLine myLine = new ThemisAnalysisLine(pLine);
184         myLine.stripEndSequence(ANON);
185 
186         /* Check for diamonds */
187         if (myLine.endsWithSequence(DIAMOND)) {
188             myLine.stripEndSequence(DIAMOND);
189         }
190 
191         /* Check that this is an anonymous class */
192         myLine.stripLastToken();
193         final String myKey = myLine.peekLastToken();
194         return ThemisAnalysisKeyWord.NEW.getKeyWord().equals(myKey);
195     }
196 }