/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2002,2008 Oracle. All rights reserved. * * $Id: CollectionProxy.java,v 1.1 2008/02/07 17:12:27 mark Exp $ */ package com.sleepycat.persist.impl; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.TreeSet; import com.sleepycat.bind.tuple.TupleBase; import com.sleepycat.db.DatabaseEntry; import com.sleepycat.persist.model.Persistent; import com.sleepycat.persist.model.PersistentProxy; import com.sleepycat.persist.raw.RawObject; /** * Proxy for Collection types. * * @author Mark Hayes */ @Persistent abstract class CollectionProxy implements PersistentProxy> { private E[] elements; protected CollectionProxy() {} public final void initializeProxy(Collection collection) { elements = (E[]) new Object[collection.size()]; int i = 0; for (E element : collection) { elements[i] = element; i += 1; } } public final Collection convertProxy() { Collection collection = newInstance(elements.length); for (E element : elements) { collection.add(element); } return collection; } protected abstract Collection newInstance(int size); @Persistent(proxyFor=ArrayList.class) static class ArrayListProxy extends CollectionProxy { protected ArrayListProxy() {} protected Collection newInstance(int size) { return new ArrayList(size); } } @Persistent(proxyFor=LinkedList.class) static class LinkedListProxy extends CollectionProxy { protected LinkedListProxy() {} protected Collection newInstance(int size) { return new LinkedList(); } } @Persistent(proxyFor=HashSet.class) static class HashSetProxy extends CollectionProxy { protected HashSetProxy() {} protected Collection newInstance(int size) { return new HashSet(size); } } @Persistent(proxyFor=TreeSet.class) static class TreeSetProxy extends CollectionProxy { protected TreeSetProxy() {} protected Collection newInstance(int size) { return new TreeSet(); } } static Object[] getElements(RawObject collection) { Object value = null; while (value == null && collection != null) { Map values = collection.getValues(); if (values != null) { value = values.get("elements"); if (value == null) { collection = collection.getSuper(); } } } if (value == null || !(value instanceof RawObject)) { throw new IllegalStateException ("Collection proxy for a secondary key field must " + "contain a field named 'elements'"); } RawObject rawObj = (RawObject) value; Format format = (Format) rawObj.getType(); if (!format.isArray() || format.getComponentType().getId() != Format.ID_OBJECT) { throw new IllegalStateException ("Collection proxy 'elements' field must by an Object array"); } return rawObj.getElements(); } static void setElements(RawObject collection, Object[] elements) { RawObject value = null; while (value == null && collection != null) { Map values = collection.getValues(); if (values != null) { value = (RawObject) values.get("elements"); if (value != null) { values.put("elements", new RawObject(value.getType(), elements)); } else { collection = collection.getSuper(); } } } if (value == null) { throw new IllegalStateException(); } } static void copyElements(RecordInput input, Format format, Format keyFormat, Set results) { /* * This could be optimized by traversing the byte format of the * collection's elements array. */ RawObject collection = (RawObject) format.newInstance(input, true); collection = (RawObject) format.readObject(collection, input, true); Object[] elements = getElements(collection); if (elements != null) { for (Object elem : elements) { RecordOutput output = new RecordOutput(input.getCatalog(), true); output.writeKeyObject(elem, keyFormat); DatabaseEntry entry = new DatabaseEntry(); TupleBase.outputToEntry(output, entry); results.add(entry); } } } }