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.cnd.modelimpl.csm;
043:
044: import org.netbeans.modules.cnd.api.model.util.CsmBaseUtilities;
045: import org.netbeans.modules.cnd.api.model.*;
046: import antlr.collections.AST;
047: import java.io.DataInput;
048: import java.io.DataOutput;
049: import java.io.IOException;
050: import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
051: import org.netbeans.modules.cnd.modelimpl.parser.generated.CPPTokenTypes;
052: import org.netbeans.modules.cnd.modelimpl.csm.core.*;
053: import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
054: import org.netbeans.modules.cnd.modelimpl.textcache.QualifiedNameCache;
055: import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
056: import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
057: import org.netbeans.modules.cnd.modelimpl.textcache.NameCache;
058:
059: /**
060: * CsmInheritance implementation
061: * @author Vladimir Kvashin
062: */
063: public class InheritanceImpl extends OffsetableBase implements
064: CsmInheritance {
065:
066: private CsmVisibility visibility;
067: private boolean virtual;
068:
069: private CsmUID<CsmClass> resolvedAncestorClassCacheUID;
070:
071: private CsmUID<CsmClassifier> classifierCacheUID;
072:
073: private CharSequence ancestorName;
074:
075: public InheritanceImpl(AST ast, CsmFile file) {
076: super (ast, file);
077: render(ast);
078: }
079:
080: public boolean isVirtual() {
081: return virtual;
082: }
083:
084: public CsmVisibility getVisibility() {
085: return visibility;
086: }
087:
088: public CsmClass getCsmClass() {
089: return getCsmClass(null);
090: }
091:
092: public CsmClass getCsmClass(Resolver parent) {
093: CsmClass ancestorCache = _getAncestorCache();
094: if (ancestorCache == null || !ancestorCache.isValid()) {
095: ancestorCache = null;
096: CsmClassifier classifier = getCsmClassifier(parent);
097: classifier = CsmBaseUtilities
098: .getOriginalClassifier(classifier);
099: if (CsmKindUtilities.isClass(classifier)) {
100: ancestorCache = (CsmClass) classifier;
101: }
102: _setAncestorCache(ancestorCache);
103: }
104: return ancestorCache;
105: }
106:
107: public CsmClassifier getCsmClassifier() {
108: return getCsmClassifier(null);
109: }
110:
111: public CsmClassifier getCsmClassifier(Resolver parent) {
112: CsmClassifier classifierCache = _getClassifierCache();
113: if (classifierCache == null
114: || ((classifierCache instanceof CsmValidable) && !((CsmValidable) classifierCache)
115: .isValid())) {
116: classifierCache = renderClassifier(ancestorName, parent);
117: _setClassifierCache(classifierCache);
118: }
119: return classifierCache;
120: }
121:
122: private void render(AST node) {
123: visibility = CsmVisibility.PRIVATE;
124: for (AST token = node.getFirstChild(); token != null; token = token
125: .getNextSibling()) {
126: switch (token.getType()) {
127: case CPPTokenTypes.LITERAL_private:
128: visibility = CsmVisibility.PRIVATE;
129: break;
130: case CPPTokenTypes.LITERAL_public:
131: visibility = CsmVisibility.PUBLIC;
132: break;
133: case CPPTokenTypes.LITERAL_protected:
134: visibility = CsmVisibility.PROTECTED;
135: break;
136: case CPPTokenTypes.LITERAL_virtual:
137: virtual = true;
138: break;
139: case CPPTokenTypes.ID:
140: StringBuilder ancNameBuffer = new StringBuilder();
141: int counter = 0;
142: for (; token != null; token = token.getNextSibling()) {
143: switch (token.getType()) {
144: case CPPTokenTypes.ID:
145: ancNameBuffer.append(token.getText());
146: break;
147: case CPPTokenTypes.SCOPE:
148: ancNameBuffer.append("::"); // NOI18N
149: counter++;
150: break;
151: default:
152: // here can be "<", ">" and other template stuff
153: }
154: }
155: //CsmObject o = ResolverFactory.createResolver(this).resolve(new String[] { token.getText() } );
156: this .ancestorName = ancNameBuffer.toString();
157: this .ancestorName = counter == 0 ? NameCache
158: .getManager().getString(this .ancestorName)
159: : QualifiedNameCache.getManager().getString(
160: this .ancestorName);
161: return; // it's definitely the last!; besides otherwise we get NPE in for
162: //break;
163: }
164: }
165: }
166:
167: private CsmClassifier renderClassifier(CharSequence ancName,
168: Resolver parent) {
169: CsmClassifier result = null;
170: CsmObject o = ResolverFactory.createResolver(this , parent)
171: .resolve(ancName, Resolver.CLASSIFIER);
172: if (CsmKindUtilities.isClassifier(o)) {
173: result = (CsmClassifier) o;
174: }
175: return result;
176: }
177:
178: public CsmClass _getAncestorCache() {
179: // can be null if cached one was removed
180: return UIDCsmConverter
181: .UIDtoDeclaration(resolvedAncestorClassCacheUID);
182: }
183:
184: public void _setAncestorCache(CsmClass ancestorCache) {
185: resolvedAncestorClassCacheUID = UIDCsmConverter
186: .declarationToUID(ancestorCache);
187: assert (resolvedAncestorClassCacheUID != null || ancestorCache == null);
188: }
189:
190: private CsmClassifier _getClassifierCache() {
191: CsmClassifier classifierCache = UIDCsmConverter
192: .UIDtoDeclaration(classifierCacheUID);
193: // can be null if cached one was removed
194: return classifierCache;
195: }
196:
197: private void _setClassifierCache(CsmClassifier classifierCache) {
198: classifierCacheUID = UIDCsmConverter
199: .declarationToUID(classifierCache);
200: assert (classifierCacheUID != null || classifierCacheUID == null);
201: }
202:
203: ////////////////////////////////////////////////////////////////////////////
204: // impl of persistent
205:
206: @Override
207: public void write(DataOutput output) throws IOException {
208: super .write(output);
209: PersistentUtils.writeVisibility(this .visibility, output);
210: output.writeBoolean(this .virtual);
211: assert this .ancestorName != null;
212: output.writeUTF(ancestorName.toString());
213:
214: // save cache
215: UIDObjectFactory.getDefaultFactory().writeUID(
216: classifierCacheUID, output);
217: boolean theSame = ((CsmUID) resolvedAncestorClassCacheUID == (CsmUID) classifierCacheUID);
218: output.writeBoolean(theSame);
219: if (!theSame) {
220: UIDObjectFactory.getDefaultFactory().writeUID(
221: resolvedAncestorClassCacheUID, output);
222: }
223: }
224:
225: public InheritanceImpl(DataInput input) throws IOException {
226: super (input);
227: this .visibility = PersistentUtils.readVisibility(input);
228: this .virtual = input.readBoolean();
229: this .ancestorName = input.readUTF();
230: this .ancestorName = ancestorName.toString().indexOf("::") == -1 ? NameCache
231: .getManager().getString(ancestorName)
232: : QualifiedNameCache.getManager().getString(
233: ancestorName); // NOI18N
234: assert this .ancestorName != null;
235:
236: // restore cached value
237: this .classifierCacheUID = UIDObjectFactory.getDefaultFactory()
238: .readUID(input);
239: boolean theSame = input.readBoolean();
240: if (!theSame) {
241: this .resolvedAncestorClassCacheUID = UIDObjectFactory
242: .getDefaultFactory().readUID(input);
243: } else {
244: this .resolvedAncestorClassCacheUID = (CsmUID) this .classifierCacheUID;
245: }
246: }
247:
248: @Override
249: public String toString() {
250: return "INHERITANCE " + visibility + " "
251: + (isVirtual() ? "virtual " : "") + ancestorName
252: + getOffsetString(); // NOI18N
253: }
254: }
|