001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.uml.core.reverseengineering.parsingfacilities;
043:
044: import java.util.Stack;
045:
046: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.AttributeStateHandler;
047: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.ClassStateHandler;
048: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.StaticDependencyStateHandler;
049: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.TemplateClassStateHandler;
050: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.EnumStateHandler;
051: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.DependencyStateHandler;
052: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.InterfaceStateHandler;
053: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.OperationStateHandler;
054: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.PackageStateHandler;
055: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.StateHandler;
056: import org.netbeans.modules.uml.core.reverseengineering.parsingfacilities.translation.statehandlers.TemplateInterfaceStateHandler;
057: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.IStateFilter;
058: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.IStateListener;
059: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.IStatePayload;
060: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ITokenDescriptor;
061: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ITokenFilter;
062: import org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ITokenProcessor;
063:
064: /**
065: */
066: public class JavaUMLParserProcessor implements IJavaUMLParserProcessor,
067: IStateFilter, IStateListener, ITokenProcessor, ITokenFilter {
068: /**
069: * ProcessState determines if a state is to be filtered or not.
070: *
071: * @param stateName [in] The name of the state.
072: * @param pVal [out] True if the state is to be processed, false otherwise.
073: */
074: public boolean processState(String stateName, String language) {
075: // I want to filter out all states that are inside of an operation.
076: // However I still want to listen to tokens found in a operation.
077: // I want the "Method Body Start" and "Method Body End" tokens.
078: // So, I do not want to filter out the "Method Body" state itself.
079: boolean ret = !m_InOperationBody;
080: if ("Method Body".equals(stateName))
081: m_InOperationBody = true;
082: return ret;
083: }
084:
085: /**
086: * The OnBeginState event is fired when the state of the parser has changed.
087: * A new state can begin while still in a state."
088: *
089: * @param stateName [in] The name of the state.
090: * @param payload [in] Extra data.
091: */
092: public void onBeginState(String stateName, String language,
093: IStatePayload Payload) {
094: addStateHandler(stateName, language);
095: }
096:
097: /**
098: * The OnEndState event will be fired when exiting a state.
099: *
100: * @param stateName [in] The name of the state.
101: */
102: public void onEndState(String stateName) {
103: removeStateHandler(stateName);
104:
105: // We we reached the end state I know that we are no longer in the
106: // operation body. At best we are just leaving the operation body.
107: m_InOperationBody = false;
108: }
109:
110: /**
111: * Process the token that has been discovered by the parser.
112: *
113: * pToken [in] The token to be processed.
114: */
115: public void processToken(ITokenDescriptor pToken, String language) {
116: if (m_StateHandlers.size() > 0) {
117: HandlerData data = m_StateHandlers.peek();
118: if (data.handler != null)
119: data.handler.processToken(pToken, language);
120: }
121: }
122:
123: protected void addStateHandler(String stateName, String language) {
124: HandlerData data = new HandlerData();
125: data.stateName = stateName;
126:
127: if (m_StateHandlers.size() > 0) {
128: HandlerData handler = m_StateHandlers.peek();
129: if (handler.handler != null) {
130: data.handler = handler.handler.createSubStateHandler(
131: stateName, language);
132:
133: // I do not want to initialize the handler twice. So, if the returned
134: // handler is the same as the current handler (in other words
135: // CreateSubStateHandler returned the THIS pointe), then do not initialize
136: // the handler. The handler has already been initialized.
137: if (data.handler != handler.handler
138: && data.handler != null)
139: data.handler.initialize();
140: }
141: } else if ("Package".equals(stateName)) {
142: data.handler = new PackageStateHandler(language);
143: data.handler.initialize();
144: } else if ("Dependency".equals(stateName)) {
145: data.handler = new DependencyStateHandler(language);
146: data.handler.initialize();
147: } else if ("Static Dependency".equals(stateName)) {
148: data.handler = new StaticDependencyStateHandler(language);
149: data.handler.initialize();
150: } else if ("Class Declaration".equals(stateName)) {
151: //data.handler = new ClassStateHandler(language, m_CurrentPackage);
152: data.handler = new TemplateClassStateHandler(language,
153: m_CurrentPackage);
154: data.handler.initialize();
155: } else if ("Enumeration Declaration".equals(stateName)) {
156: data.handler = new EnumStateHandler(language,
157: m_CurrentPackage);
158: data.handler.initialize();
159: } else if ("Interface Declaration".equals(stateName)) {
160: data.handler = new TemplateInterfaceStateHandler(language,
161: m_CurrentPackage);
162: data.handler.initialize();
163: } else if ("Variable Definition".equals(stateName)) {
164: data.handler = new AttributeStateHandler(language,
165: stateName);
166: data.handler.initialize();
167: } else if ("Method Definition".equals(stateName)) {
168: data.handler = new OperationStateHandler(language,
169: stateName, OperationStateHandler.OPERATION);
170: data.handler.initialize();
171: } else if ("Constructor Definition".equals(stateName)) {
172: data.handler = new OperationStateHandler(language,
173: stateName, OperationStateHandler.CONSTRUCTOR);
174: data.handler.initialize();
175: } else if ("Destructor Definition".equals(stateName)) {
176: data.handler = new OperationStateHandler(language,
177: stateName, OperationStateHandler.DESTRUCTOR);
178: data.handler.initialize();
179: }
180:
181: m_StateHandlers.push(data);
182: }
183:
184: protected void removeStateHandler(String stateName) {
185: if (m_StateHandlers.size() > 0) {
186: HandlerData oldData = m_StateHandlers.pop();
187:
188: // Remove the hander from the stack and notify the handler that
189: // the state has ended.
190: if (oldData.handler != null) {
191: oldData.handler.stateComplete(stateName);
192:
193: if ("Package".equals(oldData.stateName)) {
194: PackageStateHandler pd = (PackageStateHandler) oldData.handler;
195: if (pd != null)
196: m_CurrentPackage = pd.getFullPackageName();
197: }
198: }
199: }
200: }
201:
202: protected void cleanUpStateHandlers() {
203: // Cycle through the states that have not been completed yet.
204: // Act as if they have beed completed. This wil force all
205: // data to be sent to the listeners. This should only occur
206: // if something terrible has happened while processing
207: // the source file. Example Stack Overflow error.
208: while (m_StateHandlers.size() > 0)
209: removeStateHandler(m_StateHandlers.peek().stateName);
210: }
211:
212: /* (non-Javadoc)
213: * @see org.netbeans.modules.uml.core.reverseengineering.reframework.parsingframework.ITokenFilter#isTokenValid(java.lang.String, java.lang.String, java.lang.String)
214: */
215: public boolean isTokenValid(String tokenType, String stateName,
216: String language) {
217: // I want to filter out all states that are inside of an operation.
218: // However I still want to listen to tokens found in a operation.
219: // I want the "Method Body Start" and "Method Body End" tokens.
220: // So, I do not want to filter out the "Method Body" state itself.
221: return !(m_InOperationBody
222: && !"Method Body Start".equals(tokenType) && !"Method Body End"
223: .equals(tokenType));
224: }
225:
226: protected static class HandlerData {
227: public StateHandler handler;
228: public String stateName;
229: }
230:
231: protected Stack<HandlerData> m_StateHandlers = new Stack<HandlerData>();
232: private boolean m_InOperationBody;
233: protected String m_CurrentPackage;
234: }
|