001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal.handlers;
022:
023: import com.db4o.*;
024: import com.db4o.foundation.*;
025: import com.db4o.internal.*;
026: import com.db4o.internal.mapping.*;
027: import com.db4o.internal.marshall.*;
028: import com.db4o.internal.query.processor.*;
029: import com.db4o.marshall.*;
030: import com.db4o.reflect.*;
031: import com.db4o.reflect.generic.GenericReflector;
032:
033: /**
034: * @exclude
035: */
036: public class ArrayHandler extends VariableLengthTypeHandler implements
037: FirstClassHandler, Comparable4 {
038:
039: public final TypeHandler4 _handler;
040: public final boolean _usePrimitiveClassReflector;
041:
042: public ArrayHandler(ObjectContainerBase container,
043: TypeHandler4 handler, boolean usePrimitiveClassReflector) {
044: super (container);
045: _handler = handler;
046: _usePrimitiveClassReflector = usePrimitiveClassReflector;
047: }
048:
049: protected ArrayHandler(TypeHandler4 template) {
050: this (((ArrayHandler) template).container(),
051: ((ArrayHandler) template)._handler,
052: ((ArrayHandler) template)._usePrimitiveClassReflector);
053: }
054:
055: protected ReflectArray arrayReflector() {
056: return container().reflector().array();
057: }
058:
059: public Object[] allElements(Object a_object) {
060: return allElements(arrayReflector(), a_object);
061: }
062:
063: public static Object[] allElements(final ReflectArray reflectArray,
064: Object array) {
065: Object[] all = new Object[reflectArray.getLength(array)];
066: for (int i = all.length - 1; i >= 0; i--) {
067: all[i] = reflectArray.get(array, i);
068: }
069: return all;
070: }
071:
072: public final void cascadeActivation(Transaction trans,
073: Object onObject, int depth, boolean activate) {
074:
075: if (!(_handler instanceof ClassMetadata)) {
076: return;
077: }
078:
079: depth--;
080:
081: Object[] all = allElements(onObject);
082: if (activate) {
083: for (int i = all.length - 1; i >= 0; i--) {
084: container().stillToActivate(trans, all[i], depth);
085: }
086: } else {
087: for (int i = all.length - 1; i >= 0; i--) {
088: container().stillToDeactivate(trans, all[i], depth,
089: false);
090: }
091: }
092:
093: }
094:
095: public ReflectClass classReflector() {
096: if (_handler instanceof BuiltinTypeHandler) {
097: return ((BuiltinTypeHandler) _handler).classReflector();
098: }
099: if (_handler instanceof ClassMetadata) {
100: return ((ClassMetadata) _handler).classReflector();
101: }
102: return container().handlers()
103: .classReflectorForHandler(_handler);
104: }
105:
106: public final TreeInt collectIDs(MarshallerFamily mf, TreeInt tree,
107: StatefulBuffer reader) throws Db4oIOException {
108: return mf._array.collectIDs(this , tree, reader);
109: }
110:
111: public final TreeInt collectIDs1(Transaction trans, TreeInt tree,
112: Buffer reader) {
113: if (reader == null) {
114: return tree;
115: }
116: if (Deploy.debug) {
117: reader.readBegin(identifier());
118: }
119: int count = elementCount(trans, reader);
120: for (int i = 0; i < count; i++) {
121: tree = (TreeInt) Tree.add(tree, new TreeInt(reader
122: .readInt()));
123: }
124: return tree;
125: }
126:
127: public final void deleteEmbedded(MarshallerFamily mf,
128: StatefulBuffer a_bytes) throws Db4oIOException {
129: mf._array.deleteEmbedded(this , a_bytes);
130: }
131:
132: // FIXME: This code has not been called in any test case when the
133: // new ArrayMarshaller was written.
134: // Apparently it only frees slots.
135: // For now the code simply returns without freeing.
136: /** @param classPrimitive */
137: public final void deletePrimitiveEmbedded(StatefulBuffer a_bytes,
138: PrimitiveFieldHandler classPrimitive) {
139:
140: a_bytes.readInt(); //int address = a_bytes.readInt();
141: a_bytes.readInt(); //int length = a_bytes.readInt();
142:
143: if (true) {
144: return;
145: }
146:
147: }
148:
149: /** @param trans */
150: public int elementCount(Transaction trans, SlotBuffer reader) {
151: int typeOrLength = reader.readInt();
152: if (typeOrLength >= 0) {
153: return typeOrLength;
154: }
155: return reader.readInt();
156: }
157:
158: public boolean equals(Object obj) {
159: if (!(obj instanceof ArrayHandler)) {
160: return false;
161: }
162: if (((ArrayHandler) obj).identifier() != identifier()) {
163: return false;
164: }
165: return (_handler.equals(((ArrayHandler) obj)._handler));
166: }
167:
168: public int hashCode() {
169: int hc = _handler.hashCode() >> 7;
170: return _usePrimitiveClassReflector ? hc : -hc;
171: }
172:
173: protected boolean handleAsByteArray(Object obj) {
174: if (Deploy.csharp) {
175: return obj.getClass() == byte[].class;
176: }
177: return obj instanceof byte[];
178: }
179:
180: public byte identifier() {
181: return Const4.YAPARRAY;
182: }
183:
184: /** @param obj */
185: public int ownLength(Object obj) {
186: return ownLength();
187: }
188:
189: private int ownLength() {
190: return Const4.OBJECT_LENGTH + Const4.INT_LENGTH * 2;
191: }
192:
193: public ReflectClass primitiveClassReflector() {
194: return Handlers4.primitiveClassReflector(_handler);
195: }
196:
197: protected Object readCreate(Transaction trans, ReadBuffer buffer,
198: IntByRef elements) {
199: ReflectClassByRef classByRef = new ReflectClassByRef();
200: elements.value = readElementsAndClass(trans, buffer, classByRef);
201: ReflectClass clazz = newInstanceReflectClass(classByRef);
202: if (clazz == null) {
203: return null;
204: }
205: return arrayReflector().newInstance(clazz, elements.value);
206: }
207:
208: protected ReflectClass newInstanceReflectClass(
209: ReflectClassByRef byRef) {
210: if (_usePrimitiveClassReflector) {
211: return primitiveClassReflector();
212: }
213: return byRef.value;
214: }
215:
216: public TypeHandler4 readArrayHandler(Transaction a_trans,
217: MarshallerFamily mf, Buffer[] a_bytes) {
218: return this ;
219: }
220:
221: public void readCandidates(int handlerVersion, Buffer reader,
222: QCandidates candidates) throws Db4oIOException {
223: reader.seek(reader.readInt());
224: readSubCandidates(handlerVersion, reader, candidates);
225: }
226:
227: public void readSubCandidates(int handlerVersion, Buffer reader,
228: QCandidates candidates) {
229: if (Deploy.debug) {
230: reader.readBegin(identifier());
231: }
232: IntByRef elements = new IntByRef();
233: Object arr = readCreate(candidates.i_trans, reader, elements);
234: if (arr == null) {
235: return;
236: }
237: readSubCandidates(handlerVersion, reader, candidates,
238: elements.value);
239: }
240:
241: protected void readSubCandidates(int handlerVersion, Buffer reader,
242: QCandidates candidates, int count) {
243: QueryingReadContext context = new QueryingReadContext(
244: candidates.transaction(), handlerVersion, reader);
245: for (int i = 0; i < count; i++) {
246: QCandidate qc = candidates.readSubCandidate(context,
247: _handler);
248: if (qc != null) {
249: candidates.addByIdentity(qc);
250: }
251: }
252: }
253:
254: final int readElementsAndClass(Transaction trans,
255: ReadBuffer buffer, ReflectClassByRef clazz) {
256: int elements = buffer.readInt();
257: if (elements < 0) {
258: clazz.value = reflectClassFromElementsEntry(trans, elements);
259: elements = buffer.readInt();
260: } else {
261: clazz.value = classReflector();
262: }
263: if (Debug.exceedsMaximumArrayEntries(elements,
264: _usePrimitiveClassReflector)) {
265: return 0;
266: }
267: return elements;
268: }
269:
270: final protected int mapElementsEntry(int orig, IDMapping mapping) {
271: if (orig >= 0 || orig == Const4.IGNORE_ID) {
272: return orig;
273: }
274: boolean primitive = !Deploy.csharp && orig < Const4.PRIMITIVE;
275: if (primitive) {
276: orig -= Const4.PRIMITIVE;
277: }
278: int origID = -orig;
279: int mappedID = mapping.mappedID(origID);
280: int mapped = -mappedID;
281: if (primitive) {
282: mapped += Const4.PRIMITIVE;
283: }
284: return mapped;
285: }
286:
287: private ReflectClass reflectClassFromElementsEntry(
288: Transaction trans, int elements) {
289:
290: // TODO: Here is a low-frequency mistake, extremely unlikely.
291: // If YapClass-ID == 99999 by accident then we will get ignore.
292:
293: if (elements != Const4.IGNORE_ID) {
294: boolean primitive = false;
295: if (!Deploy.csharp) {
296: if (elements < Const4.PRIMITIVE) {
297: primitive = true;
298: elements -= Const4.PRIMITIVE;
299: }
300: }
301: int classID = -elements;
302: ClassMetadata classMetadata = trans.container()
303: .classMetadataForId(classID);
304: if (classMetadata != null) {
305: return (primitive ? Handlers4
306: .primitiveClassReflector(classMetadata)
307: : classMetadata.classReflector());
308: }
309: }
310: return classReflector();
311: }
312:
313: public static Object[] toArray(ObjectContainerBase stream,
314: Object obj) {
315: final GenericReflector reflector = stream.reflector();
316: ReflectClass claxx = reflector.forObject(obj);
317: ReflectArray reflectArray = reflector.array();
318: if (reflectArray.isNDimensional(claxx)) {
319: return MultidimensionalArrayHandler.allElements(
320: reflectArray, obj);
321: }
322: return ArrayHandler.allElements(reflectArray, obj);
323: }
324:
325: protected final int classID(Object obj) {
326: ReflectClass claxx = componentType(obj);
327: boolean primitive = Deploy.csharp ? false : claxx.isPrimitive();
328: if (primitive) {
329: claxx = container()._handlers.classMetadataForClass(
330: container(), claxx).classReflector();
331: }
332: ClassMetadata classMetadata = container().produceClassMetadata(
333: claxx);
334: if (classMetadata == null) {
335: // TODO: This one is a terrible low-frequency blunder !!!
336: // If YapClass-ID == 99999 then we will get IGNORE back.
337: // Discovered on adding the primitives
338: return Const4.IGNORE_ID;
339: }
340: int classID = classMetadata.getID();
341: if (primitive) {
342: classID -= Const4.PRIMITIVE;
343: }
344: return -classID;
345: }
346:
347: private ReflectClass componentType(Object obj) {
348: return arrayReflector().getComponentType(
349: reflector().forObject(obj));
350: }
351:
352: private Reflector reflector() {
353: return container().reflector();
354: }
355:
356: // Comparison_______________________
357:
358: public Comparable4 prepareComparison(Object obj) {
359: _handler.prepareComparison(obj);
360: return this ;
361: }
362:
363: public int compareTo(Object a_obj) {
364: return -1;
365: }
366:
367: public boolean isEqual(Object obj) {
368: if (obj == null) {
369: return false;
370: }
371: Object[] compareWith = allElements(obj);
372: for (int j = 0; j < compareWith.length; j++) {
373: if (_handler.compareTo(compareWith[j]) == 0) {
374: return true;
375: }
376: }
377: return false;
378: }
379:
380: public boolean isGreater(Object obj) {
381: Object[] compareWith = allElements(obj);
382: for (int j = 0; j < compareWith.length; j++) {
383: if (_handler.compareTo(compareWith[j]) > 0) {
384: return true;
385: }
386: }
387: return false;
388: }
389:
390: public boolean isSmaller(Object obj) {
391: Object[] compareWith = allElements(obj);
392: for (int j = 0; j < compareWith.length; j++) {
393: if (_handler.compareTo(compareWith[j]) < 0) {
394: return true;
395: }
396: }
397: return false;
398: }
399:
400: public final void defrag(MarshallerFamily mf, BufferPair readers,
401: boolean redirect) {
402: if (Handlers4.handlesSimple(_handler)) {
403: readers.incrementOffset(linkLength());
404: } else {
405: mf._array.defragIDs(this , readers);
406: }
407: }
408:
409: public void defrag1(MarshallerFamily mf, BufferPair readers) {
410: if (Deploy.debug) {
411: readers.readBegin(identifier());
412: }
413: int elements = readElementsDefrag(readers);
414: for (int i = 0; i < elements; i++) {
415: _handler.defrag(mf, readers, true);
416: }
417: if (Deploy.debug) {
418: readers.readEnd();
419: }
420: }
421:
422: protected int readElementsDefrag(BufferPair readers) {
423: int elements = readers.source().readInt();
424: readers.target().writeInt(
425: mapElementsEntry(elements, readers.mapping()));
426: if (elements < 0) {
427: elements = readers.readInt();
428: }
429: return elements;
430: }
431:
432: public Object read(ReadContext context) {
433: if (Deploy.debug) {
434: Debug.readBegin(context, Const4.YAPARRAY);
435: }
436: IntByRef elements = new IntByRef();
437: Object array = readCreate(context.transaction(), context,
438: elements);
439: if (array != null) {
440: if (handleAsByteArray(array)) {
441: context.readBytes((byte[]) array); // byte[] performance optimisation
442: } else {
443: for (int i = 0; i < elements.value; i++) {
444: arrayReflector().set(array, i,
445: context.readObject(_handler));
446: }
447: }
448: }
449: if (Deploy.debug) {
450: Debug.readEnd(context);
451: }
452: return array;
453: }
454:
455: public void write(WriteContext context, Object obj) {
456: if (Deploy.debug) {
457: Debug.writeBegin(context, Const4.YAPARRAY);
458: }
459: int classID = classID(obj);
460: context.writeInt(classID);
461: int elementCount = arrayReflector().getLength(obj);
462: context.writeInt(elementCount);
463: if (handleAsByteArray(obj)) {
464: context.writeBytes((byte[]) obj); // byte[] performance optimisation
465: } else {
466: for (int i = 0; i < elementCount; i++) {
467: context.writeObject(_handler, arrayReflector().get(obj,
468: i));
469: }
470: }
471: if (Deploy.debug) {
472: Debug.writeEnd(context);
473: }
474: }
475:
476: }
|