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.internal.*;
025: import com.db4o.internal.marshall.*;
026: import com.db4o.internal.slots.*;
027: import com.db4o.marshall.*;
028: import com.db4o.reflect.*;
029:
030: /**
031: * @exclude
032: */
033: public abstract class StringHandler extends VariableLengthTypeHandler
034: implements IndexableTypeHandler, BuiltinTypeHandler {
035:
036: public StringHandler(ObjectContainerBase container) {
037: super (container);
038: }
039:
040: protected StringHandler(TypeHandler4 template) {
041: this (((StringHandler) template).container());
042: }
043:
044: public ReflectClass classReflector() {
045: return container()._handlers.ICLASS_STRING;
046: }
047:
048: public void deleteEmbedded(MarshallerFamily mf,
049: StatefulBuffer buffer) {
050: Slot slot = buffer.readSlot();
051: if (slot.address() > 0 && !mf._string.inlinedStrings()) {
052: buffer.getTransaction().slotFreeOnCommit(slot.address(),
053: slot);
054: }
055: }
056:
057: byte getIdentifier() {
058: return Const4.YAPSTRING;
059: }
060:
061: public Object indexEntryToObject(Transaction trans,
062: Object indexEntry) {
063: if (indexEntry instanceof Slot) {
064: Slot slot = (Slot) indexEntry;
065: indexEntry = container().bufferByAddress(slot.address(),
066: slot.length());
067: }
068: return readStringNoDebug(trans.context(),
069: (ReadBuffer) indexEntry);
070: }
071:
072: /**
073: * This readIndexEntry method reads from the parent slot.
074: * TODO: Consider renaming methods in Indexable4 and Typhandler4 to make direction clear.
075: * @throws CorruptionException
076: */
077: public Object readIndexEntry(MarshallerFamily mf,
078: StatefulBuffer a_writer) throws CorruptionException,
079: Db4oIOException {
080: return mf._string.readIndexEntry(a_writer);
081: }
082:
083: /**
084: * This readIndexEntry method reads from the actual index in the file.
085: * TODO: Consider renaming methods in Indexable4 and Typhandler4 to make direction clear.
086: */
087: public Object readIndexEntry(Buffer reader) {
088: Slot s = new Slot(reader.readInt(), reader.readInt());
089: if (isInvalidSlot(s)) {
090: return null;
091: }
092: return s;
093: }
094:
095: private boolean isInvalidSlot(Slot slot) {
096: return (slot.address() == 0) && (slot.length() == 0);
097: }
098:
099: public void writeIndexEntry(Buffer writer, Object entry) {
100: if (entry == null) {
101: writer.writeInt(0);
102: writer.writeInt(0);
103: return;
104: }
105: if (entry instanceof StatefulBuffer) {
106: StatefulBuffer entryAsWriter = (StatefulBuffer) entry;
107: writer.writeInt(entryAsWriter.getAddress());
108: writer.writeInt(entryAsWriter.length());
109: return;
110: }
111: if (entry instanceof Slot) {
112: Slot s = (Slot) entry;
113: writer.writeInt(s.address());
114: writer.writeInt(s.length());
115: return;
116: }
117: throw new IllegalArgumentException();
118: }
119:
120: public final void writeShort(Transaction trans, String str,
121: Buffer buffer) {
122: if (str == null) {
123: buffer.writeInt(0);
124: } else {
125: buffer.writeInt(str.length());
126: trans.container().handlers().stringIO().write(buffer, str);
127: }
128: }
129:
130: // Comparison_______________________
131:
132: private Buffer i_compareTo;
133:
134: private Buffer val(Object obj) {
135: return val(obj, container());
136: }
137:
138: public Buffer val(Object obj, ObjectContainerBase oc) {
139: if (obj instanceof Buffer) {
140: return (Buffer) obj;
141: }
142: if (obj instanceof String) {
143: return writeToBuffer((InternalObjectContainer) oc,
144: (String) obj);
145: }
146: if (obj instanceof Slot) {
147: Slot s = (Slot) obj;
148: return oc.bufferByAddress(s.address(), s.length());
149: }
150:
151: return null;
152: }
153:
154: public Comparable4 prepareComparison(Object obj) {
155: if (obj == null) {
156: i_compareTo = null;
157: return Null.INSTANCE;
158: }
159: i_compareTo = val(obj);
160: return this ;
161: }
162:
163: public int compareTo(Object obj) {
164: if (i_compareTo == null) {
165: if (obj == null) {
166: return 0;
167: }
168: return 1;
169: }
170: return compare(i_compareTo, val(obj));
171: }
172:
173: /**
174: * returns: -x for left is greater and +x for right is greater
175: *
176: * TODO: You will need collators here for different languages.
177: */
178: final int compare(Buffer a_compare, Buffer a_with) {
179: if (a_compare == null) {
180: if (a_with == null) {
181: return 0;
182: }
183: return 1;
184: }
185: if (a_with == null) {
186: return -1;
187: }
188: return compare(a_compare._buffer, a_with._buffer);
189: }
190:
191: public static final int compare(byte[] compare, byte[] with) {
192: int min = compare.length < with.length ? compare.length
193: : with.length;
194: int start = Const4.INT_LENGTH;
195: if (Deploy.debug) {
196: start += Const4.LEADING_LENGTH;
197: min -= Const4.BRACKETS_BYTES;
198: }
199: for (int i = start; i < min; i++) {
200: if (compare[i] != with[i]) {
201: return with[i] - compare[i];
202: }
203: }
204: return with.length - compare.length;
205: }
206:
207: public void defragIndexEntry(BufferPair readers) {
208: // address
209: readers.copyID(false, true);
210: // length
211: readers.incrementIntSize();
212: }
213:
214: public void defrag(MarshallerFamily mf, BufferPair readers,
215: boolean redirect) {
216: if (!redirect) {
217: readers.incrementOffset(linkLength());
218: } else {
219: mf._string.defrag(readers);
220: }
221: }
222:
223: public abstract Object read(ReadContext context);
224:
225: public void write(WriteContext context, Object obj) {
226: internalWrite((InternalObjectContainer) context
227: .objectContainer(), context, (String) obj);
228: }
229:
230: protected static void internalWrite(
231: InternalObjectContainer objectContainer,
232: WriteBuffer buffer, String str) {
233: if (Deploy.debug) {
234: Debug.writeBegin(buffer, Const4.YAPSTRING);
235: }
236: buffer.writeInt(str.length());
237: stringIo(objectContainer).write(buffer, str);
238:
239: if (Deploy.debug) {
240: Debug.writeEnd(buffer);
241: }
242: }
243:
244: public static Buffer writeToBuffer(
245: InternalObjectContainer container, String str) {
246: Buffer buffer = new Buffer(stringIo(container).length(str));
247: internalWrite(container, buffer, str);
248: return buffer;
249: }
250:
251: protected static LatinStringIO stringIo(Context context) {
252: return stringIo((InternalObjectContainer) context
253: .objectContainer());
254: }
255:
256: protected static LatinStringIO stringIo(
257: InternalObjectContainer objectContainer) {
258: return objectContainer.container().stringIO();
259: }
260:
261: public static String readString(Context context, ReadBuffer buffer) {
262: if (Deploy.debug) {
263: Debug.readBegin(buffer, Const4.YAPSTRING);
264: }
265: String str = readStringNoDebug(context, buffer);
266: if (Deploy.debug) {
267: Debug.readEnd(buffer);
268: }
269: return str;
270: }
271:
272: public static String readStringNoDebug(Context context,
273: ReadBuffer buffer) {
274: int length = buffer.readInt();
275: if (length > 0) {
276: return intern(context, stringIo(context).read(buffer,
277: length));
278: }
279: return "";
280: }
281:
282: protected static String intern(Context context, String str) {
283: if (context.objectContainer().ext().configure().internStrings()) {
284: return str.intern();
285: }
286: return str;
287: }
288:
289: }
|