1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 * $Id: CollectionProxy.java,v 1.1 2008/02/07 17:12:27 mark Exp $ 7 */ 8 9package com.sleepycat.persist.impl; 10 11import java.util.ArrayList; 12import java.util.Collection; 13import java.util.HashSet; 14import java.util.LinkedList; 15import java.util.Map; 16import java.util.Set; 17import java.util.TreeSet; 18 19import com.sleepycat.bind.tuple.TupleBase; 20import com.sleepycat.db.DatabaseEntry; 21import com.sleepycat.persist.model.Persistent; 22import com.sleepycat.persist.model.PersistentProxy; 23import com.sleepycat.persist.raw.RawObject; 24 25/** 26 * Proxy for Collection types. 27 * 28 * @author Mark Hayes 29 */ 30@Persistent 31abstract class CollectionProxy<E> 32 implements PersistentProxy<Collection<E>> { 33 34 private E[] elements; 35 36 protected CollectionProxy() {} 37 38 public final void initializeProxy(Collection<E> collection) { 39 elements = (E[]) new Object[collection.size()]; 40 int i = 0; 41 for (E element : collection) { 42 elements[i] = element; 43 i += 1; 44 } 45 } 46 47 public final Collection<E> convertProxy() { 48 Collection<E> collection = newInstance(elements.length); 49 for (E element : elements) { 50 collection.add(element); 51 } 52 return collection; 53 } 54 55 protected abstract Collection<E> newInstance(int size); 56 57 @Persistent(proxyFor=ArrayList.class) 58 static class ArrayListProxy<E> extends CollectionProxy<E> { 59 60 protected ArrayListProxy() {} 61 62 protected Collection<E> newInstance(int size) { 63 return new ArrayList<E>(size); 64 } 65 } 66 67 @Persistent(proxyFor=LinkedList.class) 68 static class LinkedListProxy<E> extends CollectionProxy<E> { 69 70 protected LinkedListProxy() {} 71 72 protected Collection<E> newInstance(int size) { 73 return new LinkedList<E>(); 74 } 75 } 76 77 @Persistent(proxyFor=HashSet.class) 78 static class HashSetProxy<E> extends CollectionProxy<E> { 79 80 protected HashSetProxy() {} 81 82 protected Collection<E> newInstance(int size) { 83 return new HashSet<E>(size); 84 } 85 } 86 87 @Persistent(proxyFor=TreeSet.class) 88 static class TreeSetProxy<E> extends CollectionProxy<E> { 89 90 protected TreeSetProxy() {} 91 92 protected Collection<E> newInstance(int size) { 93 return new TreeSet<E>(); 94 } 95 } 96 97 static Object[] getElements(RawObject collection) { 98 Object value = null; 99 while (value == null && collection != null) { 100 Map<String,Object> values = collection.getValues(); 101 if (values != null) { 102 value = values.get("elements"); 103 if (value == null) { 104 collection = collection.getSuper(); 105 } 106 } 107 } 108 if (value == null || !(value instanceof RawObject)) { 109 throw new IllegalStateException 110 ("Collection proxy for a secondary key field must " + 111 "contain a field named 'elements'"); 112 } 113 RawObject rawObj = (RawObject) value; 114 Format format = (Format) rawObj.getType(); 115 if (!format.isArray() || 116 format.getComponentType().getId() != Format.ID_OBJECT) { 117 throw new IllegalStateException 118 ("Collection proxy 'elements' field must by an Object array"); 119 } 120 return rawObj.getElements(); 121 } 122 123 static void setElements(RawObject collection, Object[] elements) { 124 RawObject value = null; 125 while (value == null && collection != null) { 126 Map<String,Object> values = collection.getValues(); 127 if (values != null) { 128 value = (RawObject) values.get("elements"); 129 if (value != null) { 130 values.put("elements", 131 new RawObject(value.getType(), elements)); 132 } else { 133 collection = collection.getSuper(); 134 } 135 } 136 } 137 if (value == null) { 138 throw new IllegalStateException(); 139 } 140 } 141 142 static void copyElements(RecordInput input, 143 Format format, 144 Format keyFormat, 145 Set results) { 146 /* 147 * This could be optimized by traversing the byte format of the 148 * collection's elements array. 149 */ 150 RawObject collection = (RawObject) format.newInstance(input, true); 151 collection = (RawObject) format.readObject(collection, input, true); 152 Object[] elements = getElements(collection); 153 if (elements != null) { 154 for (Object elem : elements) { 155 RecordOutput output = 156 new RecordOutput(input.getCatalog(), true); 157 output.writeKeyObject(elem, keyFormat); 158 DatabaseEntry entry = new DatabaseEntry(); 159 TupleBase.outputToEntry(output, entry); 160 results.add(entry); 161 } 162 } 163 } 164} 165