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.uid;
043:
044: import java.io.DataInput;
045: import java.io.DataOutput;
046: import java.io.IOException;
047: import java.util.ArrayList;
048: import java.util.Collection;
049: import java.util.HashMap;
050: import java.util.Map;
051: import org.netbeans.modules.cnd.api.model.CsmUID;
052: import org.netbeans.modules.cnd.utils.cache.APTStringManager;
053: import org.netbeans.modules.cnd.modelimpl.csm.BuiltinTypes;
054: import org.netbeans.modules.cnd.modelimpl.csm.BuiltinTypes.BuiltInUID;
055: import org.netbeans.modules.cnd.modelimpl.csm.core.FileImpl;
056: import org.netbeans.modules.cnd.modelimpl.repository.KeyObjectFactory;
057: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.ClassifierUID;
058: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.DeclarationUID;
059: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.FileUID;
060: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.IncludeUID;
061: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.MacroUID;
062: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.NamespaceUID;
063: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.ProjectUID;
064: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.TypedefUID;
065: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.UnnamedClassifierUID;
066: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.UnnamedOffsetableDeclarationUID;
067: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.UnresolvedClassUID;
068: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.UnresolvedFileUID;
069: import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities.UnresolvedNamespaceUID;
070: import org.netbeans.modules.cnd.repository.support.AbstractObjectFactory;
071: import org.netbeans.modules.cnd.repository.support.SelfPersistent;
072:
073: /**
074: *
075: * @author Nickolay Dalmatov
076: */
077: public class UIDObjectFactory extends AbstractObjectFactory {
078: private static UIDObjectFactory theFactory;
079:
080: /** Creates a new instance of UIDObjectFactory */
081: protected UIDObjectFactory() {
082: }
083:
084: synchronized public static UIDObjectFactory getDefaultFactory() {
085: if (theFactory == null) {
086: theFactory = new UIDObjectFactory();
087: }
088: return theFactory;
089: }
090:
091: public void writeUID(CsmUID anUID, DataOutput aStream)
092: throws IOException {
093: assert anUID == null || anUID instanceof SelfPersistent;
094: super .writeSelfPersistent((SelfPersistent) anUID, aStream);
095: }
096:
097: public CsmUID readUID(DataInput aStream) throws IOException {
098: assert aStream != null;
099: SelfPersistent out = super .readSelfPersistent(aStream);
100: assert out == null || out instanceof CsmUID;
101: return (CsmUID) out;
102: }
103:
104: public <T> void writeUIDCollection(
105: Collection<CsmUID<T>> aCollection, DataOutput aStream,
106: boolean sync) throws IOException {
107: assert aStream != null;
108: if (aCollection == null) {
109: aStream.writeInt(NULL_POINTER);
110: } else {
111: aCollection = sync ? copySyncCollection(aCollection)
112: : aCollection;
113: int collSize = aCollection.size();
114: aStream.writeInt(collSize);
115:
116: for (CsmUID uid : aCollection) {
117: assert uid != null;
118: writeUID(uid, aStream);
119: }
120: }
121: }
122:
123: public <T extends Collection> T readUIDCollection(T aCollection,
124: DataInput aStream) throws IOException {
125: assert aCollection != null;
126: assert aStream != null;
127: int collSize = aStream.readInt();
128: if (collSize == NULL_POINTER) {
129: return null;
130: } else {
131: for (int i = 0; i < collSize; ++i) {
132: CsmUID anUID = readUID(aStream);
133: assert anUID != null;
134: aCollection.add(anUID);
135: }
136: return aCollection;
137: }
138: }
139:
140: public <T> void writeStringToUIDMap(
141: Map<CharSequence, CsmUID<T>> aMap, DataOutput aStream,
142: boolean sync) throws IOException {
143: assert aMap != null;
144: assert aStream != null;
145: aMap = sync ? copySyncMap(aMap) : aMap;
146: int collSize = aMap.size();
147: aStream.writeInt(collSize);
148:
149: for (Map.Entry<CharSequence, CsmUID<T>> anEntry : aMap
150: .entrySet()) {
151: String key = anEntry.getKey().toString();
152: assert key != null;
153: aStream.writeUTF(key);
154: CsmUID anUID = anEntry.getValue();
155: assert anUID != null;
156: writeUID(anUID, aStream);
157: }
158:
159: }
160:
161: public <T> void writeSortedStringToUIDMap(
162: Map<FileImpl.SortedKey, CsmUID<T>> aMap,
163: DataOutput aStream, boolean sync) throws IOException {
164: assert aMap != null;
165: assert aStream != null;
166: aMap = sync ? copySyncMap(aMap) : aMap;
167: int collSize = aMap.size();
168: aStream.writeInt(collSize);
169:
170: for (Map.Entry<FileImpl.SortedKey, CsmUID<T>> anEntry : aMap
171: .entrySet()) {
172: anEntry.getKey().write(aStream);
173: CsmUID anUID = anEntry.getValue();
174: assert anUID != null;
175: writeUID(anUID, aStream);
176: }
177: }
178:
179: public void writeStringToArrayUIDMap(
180: Map<CharSequence, Object> aMap, DataOutput aStream,
181: boolean sync) throws IOException {
182: assert aMap != null;
183: assert aStream != null;
184: aMap = sync ? copySyncMap(aMap) : aMap;
185: int collSize = aMap.size();
186: aStream.writeInt(collSize);
187:
188: for (Map.Entry<CharSequence, Object> anEntry : aMap.entrySet()) {
189: String key = anEntry.getKey().toString();
190: assert key != null;
191: aStream.writeUTF(key);
192: Object o = anEntry.getValue();
193: if (o instanceof CsmUID) {
194: aStream.writeInt(1);
195: writeUID((CsmUID) o, aStream);
196: } else {
197: CsmUID[] arr = (CsmUID[]) o;
198: aStream.writeInt(arr.length);
199: for (CsmUID uid : arr) {
200: assert uid != null;
201: writeUID(uid, aStream);
202: }
203: }
204: }
205: }
206:
207: private static Collection copySyncCollection(Collection col) {
208: Collection out;
209: synchronized (col) {
210: out = new ArrayList(col);
211: }
212: return out;
213: }
214:
215: private static Map copySyncMap(Map map) {
216: Map out;
217: synchronized (map) {
218: out = new HashMap(map);
219: }
220: return out;
221: }
222:
223: public <T> void readStringToUIDMap(
224: Map<CharSequence, CsmUID<T>> aMap, DataInput aStream,
225: APTStringManager manager) throws IOException {
226: assert aMap != null;
227: assert aStream != null;
228:
229: int collSize = aStream.readInt();
230:
231: for (int i = 0; i < collSize; ++i) {
232: CharSequence key = aStream.readUTF();
233: key = manager == null ? key : manager.getString(key);
234: assert key != null;
235: CsmUID uid = readUID(aStream);
236: assert uid != null;
237: aMap.put(key, uid);
238: }
239: }
240:
241: public <T> void readSortedStringToUIDMap(
242: Map<FileImpl.SortedKey, CsmUID<T>> aMap, DataInput aStream,
243: APTStringManager manager) throws IOException {
244: assert aMap != null;
245: assert aStream != null;
246:
247: int collSize = aStream.readInt();
248:
249: for (int i = 0; i < collSize; ++i) {
250: FileImpl.SortedKey key = new FileImpl.SortedKey(aStream);
251: assert key != null;
252: CsmUID uid = readUID(aStream);
253: assert uid != null;
254: aMap.put(key, uid);
255: }
256: }
257:
258: public void readStringToArrayUIDMap(Map<CharSequence, Object> aMap,
259: DataInput aStream, APTStringManager manager)
260: throws IOException {
261: assert aMap != null;
262: assert aStream != null;
263:
264: int collSize = aStream.readInt();
265:
266: for (int i = 0; i < collSize; ++i) {
267: CharSequence key = aStream.readUTF();
268: key = manager == null ? key : manager.getString(key);
269: assert key != null;
270: int arrSize = aStream.readInt();
271: if (arrSize == 1) {
272: CsmUID uid = readUID(aStream);
273: assert uid != null;
274: aMap.put(key, uid);
275: } else {
276: CsmUID[] uids = new CsmUID[arrSize];
277: for (int k = 0; k < arrSize; k++) {
278: CsmUID uid = readUID(aStream);
279: assert uid != null;
280: uids[k] = uid;
281: }
282: aMap.put(key, uids);
283: }
284: }
285: }
286:
287: protected int getHandler(Object object) {
288: int aHandler;
289:
290: if (object instanceof ProjectUID) {
291: aHandler = UID_PROJECT_UID;
292: } else if (object instanceof NamespaceUID) {
293: aHandler = UID_NAMESPACE_UID;
294: } else if (object instanceof FileUID) {
295: aHandler = UID_FILE_UID;
296: } else if (object instanceof TypedefUID) {
297: aHandler = UID_TYPEDEF_UID;
298: } else if (object instanceof ClassifierUID) {
299: aHandler = UID_CLASSIFIER_UID;
300: } else if (object instanceof UnnamedClassifierUID) {
301: aHandler = UID_UNNAMED_CLASSIFIER_UID;
302: } else if (object instanceof MacroUID) {
303: aHandler = UID_MACRO_UID;
304: } else if (object instanceof IncludeUID) {
305: aHandler = UID_INCLUDE_UID;
306: } else if (object instanceof UnnamedOffsetableDeclarationUID) {
307: aHandler = UID_UNNAMED_OFFSETABLE_DECLARATION_UID;
308: } else if (object instanceof DeclarationUID) {
309: aHandler = UID_DECLARATION_UID;
310: } else if (object instanceof BuiltInUID) {
311: aHandler = UID_BUILT_IN_UID;
312: } else if (object instanceof UnresolvedClassUID) {
313: aHandler = UID_UNRESOLVED_CLASS;
314: } else if (object instanceof UnresolvedFileUID) {
315: aHandler = UID_UNRESOLVED_FILE;
316: } else if (object instanceof UnresolvedNamespaceUID) {
317: aHandler = UID_UNRESOLVED_NAMESPACE;
318: } else {
319: throw new IllegalArgumentException(
320: "The UID is an instance of unknow class"); //NOI18N
321: }
322:
323: return aHandler;
324: }
325:
326: protected SelfPersistent createObject(int handler, DataInput aStream)
327: throws IOException {
328:
329: SelfPersistent anUID;
330: boolean share = true;
331: switch (handler) {
332: case UID_PROJECT_UID:
333: anUID = new ProjectUID(aStream);
334: break;
335:
336: case UID_NAMESPACE_UID:
337: anUID = new NamespaceUID(aStream);
338: break;
339:
340: case UID_FILE_UID:
341: anUID = new FileUID(aStream);
342: break;
343:
344: case UID_TYPEDEF_UID:
345: anUID = new TypedefUID(aStream);
346: break;
347:
348: case UID_CLASSIFIER_UID:
349: anUID = new ClassifierUID(aStream);
350: break;
351:
352: case UID_UNNAMED_CLASSIFIER_UID:
353: anUID = new UnnamedClassifierUID(aStream);
354: break;
355:
356: case UID_MACRO_UID:
357: anUID = new MacroUID(aStream);
358: break;
359:
360: case UID_INCLUDE_UID:
361: anUID = new IncludeUID(aStream);
362: break;
363:
364: case UID_UNNAMED_OFFSETABLE_DECLARATION_UID:
365: anUID = new UnnamedOffsetableDeclarationUID(aStream);
366: break;
367:
368: case UID_DECLARATION_UID:
369: anUID = new DeclarationUID(aStream);
370: break;
371:
372: case UID_BUILT_IN_UID:
373: anUID = BuiltinTypes.readUID(aStream);
374: share = false;
375: break;
376:
377: case UID_UNRESOLVED_CLASS:
378: anUID = new UIDUtilities.UnresolvedClassUID(aStream);
379: break;
380:
381: case UID_UNRESOLVED_FILE:
382: anUID = new UIDUtilities.UnresolvedFileUID(aStream);
383: break;
384:
385: case UID_UNRESOLVED_NAMESPACE:
386: anUID = new UIDUtilities.UnresolvedNamespaceUID(aStream);
387: break;
388: default:
389: throw new IllegalArgumentException(
390: "The UID is an instance of unknown class: "
391: + handler); //NOI18N
392: }
393: if (share) {
394: assert anUID != null;
395: assert anUID instanceof CsmUID;
396: CsmUID shared = UIDManager.instance().getSharedUID(
397: (CsmUID) anUID);
398: assert shared != null;
399: assert shared instanceof SelfPersistent;
400: anUID = (SelfPersistent) anUID;
401: }
402: return anUID;
403: }
404:
405: ///////////////////////////////////////////////////////////////////////////////////////////
406: // constants which defines the handle of an UID in the stream
407:
408: private static final int FIRST_INDEX = KeyObjectFactory.LAST_INDEX + 1;
409:
410: private static final int UID_PROJECT_UID = FIRST_INDEX;
411: private static final int UID_NAMESPACE_UID = UID_PROJECT_UID + 1;
412: private static final int UID_FILE_UID = UID_NAMESPACE_UID + 1;
413: private static final int UID_TYPEDEF_UID = UID_FILE_UID + 1;
414: private static final int UID_CLASSIFIER_UID = UID_TYPEDEF_UID + 1;
415: private static final int UID_UNNAMED_CLASSIFIER_UID = UID_CLASSIFIER_UID + 1;
416: private static final int UID_MACRO_UID = UID_UNNAMED_CLASSIFIER_UID + 1;
417: private static final int UID_INCLUDE_UID = UID_MACRO_UID + 1;
418: private static final int UID_UNNAMED_OFFSETABLE_DECLARATION_UID = UID_INCLUDE_UID + 1;
419: private static final int UID_DECLARATION_UID = UID_UNNAMED_OFFSETABLE_DECLARATION_UID + 1;
420: private static final int UID_BUILT_IN_UID = UID_DECLARATION_UID + 1;
421:
422: private static final int UID_UNRESOLVED_CLASS = UID_BUILT_IN_UID + 1;
423: private static final int UID_UNRESOLVED_FILE = UID_UNRESOLVED_CLASS + 1;
424: private static final int UID_UNRESOLVED_NAMESPACE = UID_UNRESOLVED_FILE + 1;
425:
426: // index to be used in another factory (but only in one)
427: // to start own indeces from the next after LAST_INDEX
428: public static final int LAST_INDEX = UID_UNRESOLVED_NAMESPACE;
429: }
|