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.core;
043:
044: import java.io.DataOutput;
045: import java.io.IOException;
046: import java.lang.ref.Reference;
047: import java.lang.ref.SoftReference;
048: import java.util.Collection;
049: import org.netbeans.modules.cnd.api.model.*;
050: import org.netbeans.modules.cnd.modelimpl.csm.*;
051: import java.util.Collections;
052: import java.util.HashMap;
053: import java.util.List;
054: import java.util.Map;
055: import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
056: import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
057: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities;
058: import org.netbeans.modules.cnd.utils.cache.CharSequenceKey;
059:
060: /**
061: * Container for all unresolved stuff in the project
062: *
063: * @author Vladimir Kvasihn
064: */
065: public final class Unresolved implements Disposable {
066:
067: private static final CharSequence UNRESOLVED = CharSequenceKey
068: .create("$unresolved file$"); // NOI18N)
069:
070: private static class IllegalCallException extends RuntimeException {
071: IllegalCallException() {
072: super ("This method should never be called for Unresolved"); // NOI18N
073: }
074: }
075:
076: public final class UnresolvedClass extends ClassEnumBase<CsmClass>
077: implements CsmClass {
078:
079: public UnresolvedClass(String name) {
080: super (name, unresolvedFile, null);
081: init(unresolvedNamespace, null);
082: }
083:
084: public void register() {
085: // we don't need registering in project here.
086: // so we just register in namespace and in repository
087: if (unresolvedNamespace != null) {
088: unresolvedNamespace.addDeclaration(this );
089: }
090: }
091:
092: public boolean isTemplate() {
093: return false;
094: }
095:
096: public Collection<CsmScopeElement> getScopeElements() {
097: return Collections.<CsmScopeElement> emptyList();
098: }
099:
100: public Collection<CsmMember> getMembers() {
101: return Collections.<CsmMember> emptyList();
102: }
103:
104: public List<CsmFriend> getFriends() {
105: return Collections.<CsmFriend> emptyList();
106: }
107:
108: public int getLeftBracketOffset() {
109: return 0;
110: }
111:
112: public List<CsmInheritance> getBaseClasses() {
113: return Collections.<CsmInheritance> emptyList();
114: }
115:
116: @Override
117: public boolean isValid() {
118: return false; // false for dummy class, to allow reconstruct in usage place
119: }
120:
121: public CsmDeclaration.Kind getKind() {
122: return CsmClass.Kind.CLASS;
123: }
124:
125: @Override
126: protected CsmUID createUID() {
127: return UIDUtilities.createUnresolvedClassUID(getName()
128: .toString(), getProject());
129: }
130:
131: ////////////////////////////////////////////////////////////////////////////
132: // impl of SelfPersistent
133: @Override
134: public void write(DataOutput output) throws IOException {
135: throw new IllegalCallException();
136: }
137: }
138:
139: private final static class UnresolvedNamespace extends
140: NamespaceImpl {
141:
142: private UnresolvedNamespace(ProjectBase project) {
143: super (project, null, "$unresolved$", "$unresolved$"); // NOI18N
144: }
145:
146: @Override
147: protected void notifyCreation() {
148: // skip registration
149: }
150:
151: @Override
152: protected CsmUID<CsmNamespace> createUID() {
153: return UIDUtilities
154: .createUnresolvedNamespaceUID(getProject());
155: }
156:
157: @Override
158: public void write(DataOutput output) throws IOException {
159: throw new IllegalCallException();
160: }
161: }
162:
163: public final class UnresolvedFile implements CsmFile {
164:
165: private UnresolvedFile() {
166: }
167:
168: public String getText(int start, int end) {
169: return "";
170: }
171:
172: public String getText() {
173: return "";
174: }
175:
176: public List<CsmScopeElement> getScopeElements() {
177: return Collections.<CsmScopeElement> emptyList();
178: }
179:
180: public CsmProject getProject() {
181: if (projectRef == null) {
182: assert projectUID != null;
183: return (ProjectBase) UIDCsmConverter
184: .UIDtoProject(projectUID);
185: } else {
186: return projectRef;
187: }
188: }
189:
190: public CharSequence getName() {
191: return UNRESOLVED; // NOI18N
192: }
193:
194: public List<CsmInclude> getIncludes() {
195: return Collections.EMPTY_LIST;
196: }
197:
198: public List<CsmOffsetableDeclaration> getDeclarations() {
199: return Collections.EMPTY_LIST;
200: }
201:
202: public String getAbsolutePath() {
203: return "$unresolved file$"; // NOI18N
204: }
205:
206: public boolean isValid() {
207: return getProject().isValid();
208: }
209:
210: public void scheduleParsing(boolean wait) {
211: }
212:
213: public boolean isParsed() {
214: return true;
215: }
216:
217: public List<CsmMacro> getMacros() {
218: return Collections.EMPTY_LIST;
219: }
220:
221: public CsmUID getUID() {
222: if (uid == null) {
223: uid = UIDUtilities.createUnresolvedFileUID(this
224: .getProject());
225: }
226: return uid;
227: }
228:
229: private CsmUID<CsmFile> uid = null;
230:
231: public boolean isSourceFile() {
232: return false;
233: }
234:
235: public boolean isHeaderFile() {
236: return true;
237: }
238: };
239:
240: // only one of projectRef/projectUID must be used (based on USE_UID_TO_CONTAINER)
241: private/*final*/ProjectBase projectRef;// can be set in onDispose or contstructor only
242: private final CsmUID<CsmProject> projectUID;
243:
244: // doesn't need Repository Keys
245: private final CsmFile unresolvedFile;
246: // doesn't need Repository Keys
247: private final NamespaceImpl unresolvedNamespace;
248: // doesn't need Repository Keys
249: private Map<String, Reference<UnresolvedClass>> dummiesForUnresolved = new HashMap<String, Reference<UnresolvedClass>>();
250:
251: public Unresolved(ProjectBase project) {
252: this .projectUID = UIDCsmConverter.projectToUID(project);
253: this .projectRef = null;
254: unresolvedFile = new UnresolvedFile();
255: unresolvedNamespace = new UnresolvedNamespace(project);
256: }
257:
258: public void dispose() {
259: onDispose();
260: }
261:
262: private void onDispose() {
263: if (TraceFlags.RESTORE_CONTAINER_FROM_UID) {
264: // restore container from it's UID
265: this .projectRef = (ProjectBase) UIDCsmConverter
266: .UIDtoProject(this .projectUID);
267: assert (this .projectRef != null || this .projectUID == null) : "empty project for UID "
268: + this .projectUID;
269: }
270: }
271:
272: public CsmClass getDummyForUnresolved(CharSequence[] nameTokens) {
273: return getDummyForUnresolved(getName(nameTokens));
274: }
275:
276: public CsmClass getDummyForUnresolved(String name) {
277: Reference<UnresolvedClass> ref = dummiesForUnresolved.get(name);
278: UnresolvedClass cls = ref == null ? null : ref.get();
279: if (cls == null) {
280: cls = new UnresolvedClass(name);
281: dummiesForUnresolved.put(name, new SoftReference(cls));
282: cls.register();
283: }
284: return cls;
285: }
286:
287: public CsmNamespace getUnresolvedNamespace() {
288: return unresolvedNamespace;
289: }
290:
291: public CsmFile getUnresolvedFile() {
292: return unresolvedFile;
293: }
294:
295: private String getName(CharSequence[] nameTokens) {
296: StringBuilder sb = new StringBuilder();
297: for (int i = 0; i < nameTokens.length; i++) {
298: if (i > 0) {
299: sb.append("::"); // NOI18N
300: }
301: sb.append(nameTokens[i]);
302: }
303: return sb.toString();
304: }
305: }
|