001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: CollectionProxy.java,v 1.8.2.2 2008/01/07 15:14:19 cwl Exp $
007: */
008:
009: package com.sleepycat.persist.impl;
010:
011: import java.util.ArrayList;
012: import java.util.Collection;
013: import java.util.HashSet;
014: import java.util.LinkedList;
015: import java.util.Map;
016: import java.util.Set;
017: import java.util.TreeSet;
018:
019: import com.sleepycat.bind.tuple.TupleBase;
020: import com.sleepycat.je.DatabaseEntry;
021: import com.sleepycat.persist.model.Persistent;
022: import com.sleepycat.persist.model.PersistentProxy;
023: import com.sleepycat.persist.raw.RawObject;
024:
025: /**
026: * Proxy for Collection types.
027: *
028: * @author Mark Hayes
029: */
030: @Persistent
031: abstract class CollectionProxy<E> implements
032: PersistentProxy<Collection<E>> {
033:
034: private E[] elements;
035:
036: protected CollectionProxy() {
037: }
038:
039: public final void initializeProxy(Collection<E> collection) {
040: elements = (E[]) new Object[collection.size()];
041: int i = 0;
042: for (E element : collection) {
043: elements[i] = element;
044: i += 1;
045: }
046: }
047:
048: public final Collection<E> convertProxy() {
049: Collection<E> collection = newInstance(elements.length);
050: for (E element : elements) {
051: collection.add(element);
052: }
053: return collection;
054: }
055:
056: protected abstract Collection<E> newInstance(int size);
057:
058: @Persistent(proxyFor=ArrayList.class)
059: static class ArrayListProxy<E> extends CollectionProxy<E> {
060:
061: protected ArrayListProxy() {
062: }
063:
064: protected Collection<E> newInstance(int size) {
065: return new ArrayList<E>(size);
066: }
067: }
068:
069: @Persistent(proxyFor=LinkedList.class)
070: static class LinkedListProxy<E> extends CollectionProxy<E> {
071:
072: protected LinkedListProxy() {
073: }
074:
075: protected Collection<E> newInstance(int size) {
076: return new LinkedList<E>();
077: }
078: }
079:
080: @Persistent(proxyFor=HashSet.class)
081: static class HashSetProxy<E> extends CollectionProxy<E> {
082:
083: protected HashSetProxy() {
084: }
085:
086: protected Collection<E> newInstance(int size) {
087: return new HashSet<E>(size);
088: }
089: }
090:
091: @Persistent(proxyFor=TreeSet.class)
092: static class TreeSetProxy<E> extends CollectionProxy<E> {
093:
094: protected TreeSetProxy() {
095: }
096:
097: protected Collection<E> newInstance(int size) {
098: return new TreeSet<E>();
099: }
100: }
101:
102: static Object[] getElements(RawObject collection) {
103: Object value = null;
104: while (value == null && collection != null) {
105: Map<String, Object> values = collection.getValues();
106: if (values != null) {
107: value = values.get("elements");
108: if (value == null) {
109: collection = collection.getSuper();
110: }
111: }
112: }
113: if (value == null || !(value instanceof RawObject)) {
114: throw new IllegalStateException(
115: "Collection proxy for a secondary key field must "
116: + "contain a field named 'elements'");
117: }
118: RawObject rawObj = (RawObject) value;
119: Format format = (Format) rawObj.getType();
120: if (!format.isArray()
121: || format.getComponentType().getId() != Format.ID_OBJECT) {
122: throw new IllegalStateException(
123: "Collection proxy 'elements' field must by an Object array");
124: }
125: return rawObj.getElements();
126: }
127:
128: static void setElements(RawObject collection, Object[] elements) {
129: RawObject value = null;
130: while (value == null && collection != null) {
131: Map<String, Object> values = collection.getValues();
132: if (values != null) {
133: value = (RawObject) values.get("elements");
134: if (value != null) {
135: values.put("elements", new RawObject(value
136: .getType(), elements));
137: } else {
138: collection = collection.getSuper();
139: }
140: }
141: }
142: if (value == null) {
143: throw new IllegalStateException();
144: }
145: }
146:
147: static void copyElements(RecordInput input, Format format,
148: Format keyFormat, Set results) {
149: /*
150: * This could be optimized by traversing the byte format of the
151: * collection's elements array.
152: */
153: RawObject collection = (RawObject) format.newInstance(input,
154: true);
155: collection = (RawObject) format.readObject(collection, input,
156: true);
157: Object[] elements = getElements(collection);
158: if (elements != null) {
159: for (Object elem : elements) {
160: RecordOutput output = new RecordOutput(input
161: .getCatalog(), true);
162: output.writeKeyObject(elem, keyFormat);
163: DatabaseEntry entry = new DatabaseEntry();
164: TupleBase.outputToEntry(output, entry);
165: results.add(entry);
166: }
167: }
168: }
169: }
|