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 antlr.collections.AST;
045: import java.io.DataInput;
046: import java.io.DataOutput;
047: import java.io.IOException;
048: import java.util.ArrayList;
049: import java.util.Collection;
050: import java.util.Collections;
051: import java.util.List;
052: import org.netbeans.modules.cnd.api.model.*;
053: import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
054: import org.netbeans.modules.cnd.modelimpl.csm.core.*;
055: import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
056: import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
057: import org.netbeans.modules.cnd.modelimpl.repository.RepositoryUtils;
058: import org.netbeans.modules.cnd.modelimpl.textcache.QualifiedNameCache;
059: import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
060: import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
061: import org.netbeans.modules.cnd.utils.cache.CharSequenceKey;
062: import org.netbeans.modules.cnd.modelimpl.textcache.NameCache;
063:
064: /**
065: * Common ancestor for ClassImpl and EnumImpl
066: * @author Vladimir Kvashin
067: */
068: public abstract class ClassEnumBase<T> extends
069: OffsetableDeclarationBase<T> implements Disposable,
070: CsmCompoundClassifier<T>, CsmMember<T> {
071:
072: private final CharSequence name;
073:
074: private/*final*/CharSequence qualifiedName;
075:
076: // only one of scopeRef/scopeAccessor must be used (based on USE_REPOSITORY)
077: private CsmScope scopeRef;// can be set in onDispose or contstructor only
078: private CsmUID<CsmScope> scopeUID;
079:
080: private boolean isValid = true;
081:
082: private boolean _static = false;
083: private CsmVisibility visibility = CsmVisibility.PRIVATE;
084: private final List<CsmUID<CsmTypedef>> enclosingTypdefs = Collections
085: .synchronizedList(new ArrayList<CsmUID<CsmTypedef>>());
086:
087: protected ClassEnumBase(String name, CsmFile file, AST ast) {
088: super (ast, file);
089: this .name = (name == null) ? CharSequenceKey.empty()
090: : NameCache.getManager().getString(name);
091: }
092:
093: public CharSequence getName() {
094: return name;
095: }
096:
097: /**
098: * Initialization method.
099: * Should be called immediately after object creation.
100: *
101: * Descendants may override it; in this case it's a descendant's responsibility
102: * to call super.init()
103: */
104: protected void init(CsmScope scope, AST ast) {
105: if (scope instanceof CsmIdentifiable) {
106: this .scopeUID = UIDCsmConverter.scopeToUID(scope);
107: assert (this .scopeUID != null || scope == null) : "null UID for class scope "
108: + scope;
109: this .scopeRef = null;
110: } else {
111: // in the case of classes/enums inside bodies
112: this .scopeRef = scope;
113: }
114:
115: CharSequence qualifiedNamePostfix = getQualifiedNamePostfix();
116: if (CsmKindUtilities.isNamespace(scope)) {
117: qualifiedName = Utils.getQualifiedName(qualifiedNamePostfix
118: .toString(), (CsmNamespace) scope);
119: } else if (CsmKindUtilities.isClass(scope)) {
120: qualifiedName = ((CsmClass) scope).getQualifiedName()
121: + "::" + qualifiedNamePostfix; // NOI18N
122: } else {
123: qualifiedName = qualifiedNamePostfix;
124: }
125: qualifiedName = QualifiedNameCache.getManager().getString(
126: qualifiedName);
127: // can't register here, because descendant class' constructor hasn't yet finished!
128: // so registering is a descendant class' responsibility
129: }
130:
131: abstract public Kind getKind();
132:
133: protected void register(CsmScope scope) {
134:
135: RepositoryUtils.put(this );
136:
137: if (ProjectBase.canRegisterDeclaration(this )) {
138: registerInProject();
139:
140: if (getContainingClass() == null) {
141: if (CsmKindUtilities.isNamespace(scope)) {
142: ((NamespaceImpl) scope).addDeclaration(this );
143: }
144: }
145: }
146: }
147:
148: private void registerInProject() {
149: ((ProjectBase) getContainingFile().getProject())
150: .registerDeclaration(this );
151: }
152:
153: private void unregisterInProject() {
154: ((ProjectBase) getContainingFile().getProject())
155: .unregisterDeclaration(this );
156: this .cleanUID();
157: }
158:
159: public NamespaceImpl getContainingNamespaceImpl() {
160: CsmScope scope = getScope();
161: return (scope instanceof NamespaceImpl) ? (NamespaceImpl) scope
162: : null;
163: }
164:
165: public CharSequence getQualifiedName() {
166: return qualifiedName;
167: }
168:
169: public CsmScope getScope() {
170: CsmScope scope = this .scopeRef;
171: if (scope == null) {
172: scope = UIDCsmConverter.UIDtoScope(this .scopeUID);
173: assert (scope != null || this .scopeUID == null) : "null object for UID "
174: + this .scopeUID;
175: }
176: return scope;
177: }
178:
179: @Override
180: public void dispose() {
181: super .dispose();
182: onDispose();
183: if (getContainingNamespaceImpl() != null) {
184: getContainingNamespaceImpl().removeDeclaration(this );
185: }
186: unregisterInProject();
187: isValid = false;
188: }
189:
190: private void onDispose() {
191: if (TraceFlags.RESTORE_CONTAINER_FROM_UID) {
192: // restore container from it's UID
193: this .scopeRef = UIDCsmConverter.UIDtoScope(this .scopeUID);
194: assert (this .scopeRef != null || this .scopeUID == null) : "empty scope for UID "
195: + this .scopeUID;
196: }
197: }
198:
199: public boolean isValid() {
200: return isValid && getContainingFile().isValid();
201: }
202:
203: public CsmClass getContainingClass() {
204: CsmScope scope = getScope();
205: return CsmKindUtilities.isClass(scope) ? (CsmClass) scope
206: : null;
207: }
208:
209: // private void setContainingClass(CsmClass cls) {
210: // containingClassRef = cls;
211: // qualifiedName = cls.getQualifiedName() + "::" + getName();
212: // }
213:
214: public CsmVisibility getVisibility() {
215: return visibility;
216: }
217:
218: public void setVisibility(CsmVisibility visibility) {
219: this .visibility = visibility;
220: }
221:
222: public boolean isStatic() {
223: return _static;
224: }
225:
226: public void setStatic(boolean _static) {
227: this ._static = _static;
228: }
229:
230: ////////////////////////////////////////////////////////////////////////////
231: // impl of SelfPersistent
232:
233: @Override
234: public void write(DataOutput output) throws IOException {
235: super .write(output);
236: output.writeBoolean(this .isValid);
237:
238: assert this .name != null;
239: output.writeUTF(this .name.toString());
240:
241: assert this .qualifiedName != null;
242: output.writeUTF(this .qualifiedName.toString());
243:
244: UIDObjectFactory.getDefaultFactory().writeUID(this .scopeUID,
245: output);
246:
247: output.writeBoolean(this ._static);
248:
249: assert this .visibility != null;
250: PersistentUtils.writeVisibility(this .visibility, output);
251:
252: // write UID for unnamed classifier
253: if (getName().length() == 0) {
254: super .writeUID(output);
255: }
256: UIDObjectFactory.getDefaultFactory().writeUIDCollection(
257: enclosingTypdefs, output, true);
258: }
259:
260: protected ClassEnumBase(DataInput input) throws IOException {
261: super (input);
262: this .isValid = input.readBoolean();
263:
264: this .name = NameCache.getManager().getString(input.readUTF());
265: assert this .name != null;
266:
267: this .qualifiedName = QualifiedNameCache.getManager().getString(
268: input.readUTF());
269: assert this .qualifiedName != null;
270:
271: this .scopeUID = UIDObjectFactory.getDefaultFactory().readUID(
272: input);
273: this .scopeRef = null;
274:
275: this ._static = input.readBoolean();
276:
277: this .visibility = PersistentUtils.readVisibility(input);
278: assert this .visibility != null;
279:
280: // restore UID for unnamed classifier
281: if (getName().length() == 0) {
282: super .readUID(input);
283: }
284: UIDObjectFactory.getDefaultFactory().readUIDCollection(
285: enclosingTypdefs, input);
286: }
287:
288: public Collection<CsmTypedef> getEnclosingTypedefs() {
289: return UIDCsmConverter.UIDsToDeclarations(enclosingTypdefs);
290: }
291:
292: public void addEnclosingTypedef(CsmTypedef typedef) {
293: enclosingTypdefs.add(typedef.getUID());
294: }
295: }
|