diff options
| author | Brian S. O'Neill <bronee@gmail.com> | 2006-10-14 16:47:22 +0000 | 
|---|---|---|
| committer | Brian S. O'Neill <bronee@gmail.com> | 2006-10-14 16:47:22 +0000 | 
| commit | 3df73d90a65115d9fdcf4b8596971e957c6bce2d (patch) | |
| tree | 12e11eb3b3ab52d5bb86a2cc7fce1d60f54d5721 /src/test/java/com/amazon/carbonado/repo/toy | |
Moved tests to separate project.
Diffstat (limited to 'src/test/java/com/amazon/carbonado/repo/toy')
5 files changed, 590 insertions, 0 deletions
diff --git a/src/test/java/com/amazon/carbonado/repo/toy/ToyRepository.java b/src/test/java/com/amazon/carbonado/repo/toy/ToyRepository.java new file mode 100644 index 0000000..159f451 --- /dev/null +++ b/src/test/java/com/amazon/carbonado/repo/toy/ToyRepository.java @@ -0,0 +1,106 @@ +/*
 + * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
 + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
 + * of Amazon Technologies, Inc. or its affiliates.  All rights reserved.
 + *
 + * Licensed under the Apache License, Version 2.0 (the "License");
 + * you may not use this file except in compliance with the License.
 + * You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +package com.amazon.carbonado.repo.toy;
 +
 +import java.util.HashMap;
 +import java.util.Map;
 +
 +import com.amazon.carbonado.IsolationLevel;
 +import com.amazon.carbonado.Repository;
 +import com.amazon.carbonado.RepositoryException;
 +import com.amazon.carbonado.Storable;
 +import com.amazon.carbonado.Storage;
 +import com.amazon.carbonado.SupportException;
 +import com.amazon.carbonado.Transaction;
 +
 +import com.amazon.carbonado.capability.Capability;
 +
 +import com.amazon.carbonado.spi.SequenceValueGenerator;
 +import com.amazon.carbonado.spi.SequenceValueProducer;
 +
 +/**
 + *
 + * @author Brian S O'Neill
 + */
 +public class ToyRepository implements Repository {
 +    private final String mName;
 +    private final Map<Class, Storage> mStorages;
 +    private final Map<String, SequenceValueProducer> mSequences;
 +
 +    public ToyRepository() {
 +        this("toy");
 +    }
 +
 +    public ToyRepository(String name) {
 +        mName = name;
 +        mStorages = new HashMap<Class, Storage>();
 +        mSequences = new HashMap<String, SequenceValueProducer>();
 +    }
 +
 +    public String getName() {
 +        return mName;
 +    }
 +
 +    public <S extends Storable> Storage<S> storageFor(Class<S> type)
 +        throws SupportException, RepositoryException
 +    {
 +        synchronized (mStorages) {
 +            Storage<S> storage = (Storage<S>) mStorages.get(type);
 +            if (storage == null) {
 +                storage = new ToyStorage<S>(this, type);
 +                mStorages.put(type, storage);
 +            }
 +            return storage;
 +        }
 +    }
 +
 +    public Transaction enterTransaction() {
 +        return new ToyTransaction();
 +    }
 +
 +    public Transaction enterTransaction(IsolationLevel level) {
 +        return enterTransaction();
 +    }
 +
 +    public Transaction enterTopTransaction(IsolationLevel level) {
 +        return enterTransaction(level);
 +    }
 +
 +    public IsolationLevel getTransactionIsolationLevel() {
 +        return null;
 +    }
 +
 +    public <C extends Capability> C getCapability(Class<C> capabilityType) {
 +        return null;
 +    }
 +
 +    public void close() {
 +    }
 +
 +    SequenceValueProducer getSequenceValueProducer(String name) throws RepositoryException {
 +        synchronized (mSequences) {
 +            SequenceValueProducer producer = mSequences.get(name);
 +            if (producer == null) {
 +                producer = new SequenceValueGenerator(this, name);
 +                mSequences.put(name, producer);
 +            }
 +            return producer;
 +        }
 +    }
 +}
 diff --git a/src/test/java/com/amazon/carbonado/repo/toy/ToyStorableGenerator.java b/src/test/java/com/amazon/carbonado/repo/toy/ToyStorableGenerator.java new file mode 100644 index 0000000..a72c7d5 --- /dev/null +++ b/src/test/java/com/amazon/carbonado/repo/toy/ToyStorableGenerator.java @@ -0,0 +1,143 @@ +/*
 + * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
 + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
 + * of Amazon Technologies, Inc. or its affiliates.  All rights reserved.
 + *
 + * Licensed under the Apache License, Version 2.0 (the "License");
 + * you may not use this file except in compliance with the License.
 + * You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +package com.amazon.carbonado.repo.toy;
 +
 +import java.util.EnumSet;
 +import java.util.Map;
 +
 +import org.cojen.classfile.ClassFile;
 +import org.cojen.classfile.CodeBuilder;
 +import org.cojen.classfile.MethodInfo;
 +import org.cojen.classfile.Modifiers;
 +import org.cojen.classfile.TypeDesc;
 +
 +import org.cojen.util.ClassInjector;
 +import org.cojen.util.SoftValuedHashMap;
 +
 +import com.amazon.carbonado.Storable;
 +import com.amazon.carbonado.SupportException;
 +import com.amazon.carbonado.Trigger;
 +
 +import com.amazon.carbonado.spi.MasterFeature;
 +import com.amazon.carbonado.spi.MasterStorableGenerator;
 +import com.amazon.carbonado.spi.MasterSupport;
 +import com.amazon.carbonado.spi.StorableGenerator;
 +import com.amazon.carbonado.spi.TriggerSupport;
 +
 +/**
 + * 
 + *
 + * @author Brian S O'Neill
 + */
 +public class ToyStorableGenerator<S extends Storable> {
 +    private static final Map<Class, Class> cCache;
 +
 +    static {
 +        cCache = new SoftValuedHashMap();
 +    }
 +
 +    /**
 +     * Generated class has a constructor that accepts a ToyStorage instance.
 +     */
 +    public static <S extends Storable> Class<? extends S> getGeneratedClass(Class<S> type)
 +        throws SupportException
 +    {
 +        synchronized (cCache) {
 +            Class<? extends S> generatedClass = (Class<? extends S>) cCache.get(type);
 +            if (generatedClass != null) {
 +                return generatedClass;
 +            }
 +            generatedClass = new ToyStorableGenerator<S>(type).generateAndInjectClass();
 +            cCache.put(type, generatedClass);
 +            return generatedClass;
 +        }
 +    }
 +
 +    private final Class<S> mStorableType;
 +
 +    private final ClassInjector mClassInjector;
 +    private final ClassFile mClassFile;
 +
 +    private ToyStorableGenerator(Class<S> type) throws SupportException {
 +        mStorableType = type;
 +
 +        EnumSet<MasterFeature> features = EnumSet
 +            .of(MasterFeature.VERSIONING, MasterFeature.INSERT_SEQUENCES);
 +
 +        final Class<? extends S> abstractClass =
 +            MasterStorableGenerator.getAbstractClass(mStorableType, features);
 +
 +        mClassInjector = ClassInjector.create(mStorableType.getName(),
 +                                              abstractClass.getClassLoader());
 +
 +        mClassFile = new ClassFile(mClassInjector.getClassName(), abstractClass);
 +        mClassFile.markSynthetic();
 +        mClassFile.setSourceFile(ToyStorableGenerator.class.getName());
 +        mClassFile.setTarget("1.5");
 +    }
 +
 +    private Class<? extends S> generateAndInjectClass() {
 +        TypeDesc masterSupportType = TypeDesc.forClass(MasterSupport.class);
 +        TypeDesc toyStorageType = TypeDesc.forClass(ToyStorage.class);
 +
 +        // Add constructor that accepts a ToyStorage.
 +        {
 +            TypeDesc[] params = {toyStorageType};
 +            MethodInfo mi = mClassFile.addConstructor(Modifiers.PUBLIC, params);
 +            CodeBuilder b = new CodeBuilder(mi);
 +            b.loadThis();
 +            b.loadLocal(b.getParameter(0));
 +            b.invokeSuperConstructor(new TypeDesc[] {masterSupportType});
 +            b.returnVoid();
 +        }
 +
 +        // Implement abstract methods which all delegate to ToyStorage instance.
 +
 +        generateDelegatedMethod
 +            (MasterStorableGenerator.DO_TRY_LOAD_MASTER_METHOD_NAME, "doTryLoad");
 +        generateDelegatedMethod
 +            (MasterStorableGenerator.DO_TRY_INSERT_MASTER_METHOD_NAME, "doTryInsert");
 +        generateDelegatedMethod
 +            (MasterStorableGenerator.DO_TRY_UPDATE_MASTER_METHOD_NAME, "doTryUpdate");
 +        generateDelegatedMethod
 +            (MasterStorableGenerator.DO_TRY_DELETE_MASTER_METHOD_NAME, "doTryDelete");
 +
 +        Class<? extends S> generatedClass = mClassInjector.defineClass(mClassFile);
 +
 +        return generatedClass;
 +    }
 +
 +    private void generateDelegatedMethod(String masterMethodName, String supportMethodName) {
 +        TypeDesc triggerSupportType = TypeDesc.forClass(TriggerSupport.class);
 +        TypeDesc toyStorageType = TypeDesc.forClass(ToyStorage.class);
 +
 +        TypeDesc[] storableParam = {TypeDesc.forClass(Storable.class)};
 +
 +        MethodInfo mi = mClassFile.addMethod
 +            (Modifiers.PROTECTED, masterMethodName, TypeDesc.BOOLEAN, null);
 +        CodeBuilder b = new CodeBuilder(mi);
 +
 +        b.loadThis();
 +        b.loadField(StorableGenerator.SUPPORT_FIELD_NAME, triggerSupportType);
 +        b.checkCast(toyStorageType);
 +        b.loadThis();
 +        b.invokeVirtual(toyStorageType, supportMethodName, TypeDesc.BOOLEAN, storableParam);
 +        b.returnValue(TypeDesc.BOOLEAN);
 +    }
 +}
 diff --git a/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java b/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java new file mode 100644 index 0000000..71a597d --- /dev/null +++ b/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java @@ -0,0 +1,265 @@ +/*
 + * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
 + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
 + * of Amazon Technologies, Inc. or its affiliates.  All rights reserved.
 + *
 + * Licensed under the Apache License, Version 2.0 (the "License");
 + * you may not use this file except in compliance with the License.
 + * You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +package com.amazon.carbonado.repo.toy;
 +
 +import java.util.Collection;
 +import java.util.Iterator;
 +import java.util.LinkedList;
 +
 +import java.util.concurrent.locks.Lock;
 +import java.util.concurrent.locks.ReentrantLock;
 +
 +import com.amazon.carbonado.FetchException;
 +import com.amazon.carbonado.IsolationLevel;
 +import com.amazon.carbonado.PersistException;
 +import com.amazon.carbonado.Query;
 +import com.amazon.carbonado.Repository;
 +import com.amazon.carbonado.RepositoryException;
 +import com.amazon.carbonado.Storable;
 +import com.amazon.carbonado.Storage;
 +import com.amazon.carbonado.SupportException;
 +import com.amazon.carbonado.Transaction;
 +import com.amazon.carbonado.Trigger;
 +
 +import com.amazon.carbonado.spi.MasterSupport;
 +import com.amazon.carbonado.spi.SequenceValueProducer;
 +
 +import com.amazon.carbonado.util.QuickConstructorGenerator;
 +
 +import com.amazon.carbonado.filter.Filter;
 +import com.amazon.carbonado.filter.FilterValues;
 +
 +import com.amazon.carbonado.info.OrderedProperty;
 +import com.amazon.carbonado.info.StorableIntrospector;
 +
 +import com.amazon.carbonado.qe.QueryExecutorFactory;
 +import com.amazon.carbonado.qe.QueryFactory;
 +import com.amazon.carbonado.qe.SortedQueryExecutor;
 +import com.amazon.carbonado.qe.FilteredQueryExecutor;
 +import com.amazon.carbonado.qe.IterableQueryExecutor;
 +import com.amazon.carbonado.qe.OrderingList;
 +import com.amazon.carbonado.qe.QueryExecutor;
 +import com.amazon.carbonado.qe.StandardQuery;
 +
 +/**
 + *
 + * @author Brian S O'Neill
 + */
 +public class ToyStorage<S extends Storable>
 +    implements Storage<S>, MasterSupport<S>, QueryFactory<S>, QueryExecutorFactory<S>
 +{
 +    final ToyRepository mRepo;
 +    final Class<S> mType;
 +
 +    final InstanceFactory mInstanceFactory;
 +
 +    final Collection<S> mData;
 +    final Lock mDataLock;
 +
 +    public ToyStorage(ToyRepository repo, Class<S> type) throws SupportException {
 +        StorableIntrospector.examine(type);
 +        mRepo = repo;
 +        mType = type;
 +
 +        Class<? extends S> generatedStorableClass = ToyStorableGenerator.getGeneratedClass(type);
 +        mInstanceFactory = QuickConstructorGenerator
 +            .getInstance(generatedStorableClass, InstanceFactory.class);
 +
 +        mData = new LinkedList<S>();
 +        mDataLock = new ReentrantLock();
 +    }
 +
 +    public Class<S> getStorableType() {
 +        return mType;
 +    }
 +
 +    public S prepare() {
 +        return (S) mInstanceFactory.instantiate(this);
 +    }
 +
 +    public Query<S> query() {
 +        return new ToyQuery(null, null, null);
 +    }
 +
 +    public Query<S> query(String filter) {
 +        return query(Filter.filterFor(mType, filter));
 +    }
 +
 +    public Query<S> query(Filter<S> filter) {
 +        return new ToyQuery(filter.initialFilterValues(), null, null);
 +    }
 +
 +    public Query<S> query(FilterValues<S> values, OrderingList<S> ordering) {
 +        return new ToyQuery(values, ordering, null);
 +    }
 +
 +    public QueryExecutor<S> executor(Filter<S> filter, OrderingList<S> ordering) {
 +        QueryExecutor<S> executor = new IterableQueryExecutor<S>(mType, mData, mDataLock);
 +
 +        if (filter != null) {
 +            executor = new FilteredQueryExecutor<S>(executor, filter);
 +        }
 +
 +        if (ordering.size() > 0) {
 +            executor = new SortedQueryExecutor<S>(null, executor, null, ordering);
 +        }
 +
 +        return executor;
 +    }
 +
 +    public boolean addTrigger(Trigger<? super S> trigger) {
 +        return false;
 +    }
 +
 +    public boolean removeTrigger(Trigger<? super S> trigger) {
 +        return false;
 +    }
 +
 +    public boolean doTryLoad(S storable) {
 +        mDataLock.lock();
 +        try {
 +            for (S existing : mData) {
 +                if (existing.equalPrimaryKeys(storable)) {
 +                    storable.markAllPropertiesDirty();
 +                    existing.copyAllProperties(storable);
 +                    storable.markAllPropertiesClean();
 +                    return true;
 +                }
 +            }
 +            return false;
 +        } finally {
 +            mDataLock.unlock();
 +        }
 +    }
 +
 +    public boolean doTryInsert(S storable) {
 +        mDataLock.lock();
 +        try {
 +            for (S existing : mData) {
 +                if (existing.equalPrimaryKeys(storable)) {
 +                    return false;
 +                }
 +            }
 +            storable.markAllPropertiesClean();
 +            mData.add((S) storable.copy());
 +            return true;
 +        } finally {
 +            mDataLock.unlock();
 +        }
 +    }
 +
 +    public boolean doTryUpdate(S storable) {
 +        mDataLock.lock();
 +        try {
 +            for (S existing : mData) {
 +                if (existing.equalPrimaryKeys(storable)) {
 +                    // Copy altered values to existing object.
 +                    existing.markAllPropertiesDirty();
 +                    storable.copyAllProperties(existing);
 +                    existing.markAllPropertiesClean();
 +
 +                    // Copy all values to user object, to simulate a reload.
 +                    storable.markAllPropertiesDirty();
 +                    existing.copyAllProperties(storable);
 +                    storable.markAllPropertiesClean();
 +
 +                    return true;
 +                }
 +            }
 +            return false;
 +        } finally {
 +            mDataLock.unlock();
 +        }
 +    }
 +
 +    public boolean doTryDelete(S storable) {
 +        mDataLock.lock();
 +        try {
 +            Iterator<S> it = mData.iterator();
 +            while (it.hasNext()) {
 +                S existing = it.next();
 +                if (existing.equalPrimaryKeys(storable)) {
 +                    it.remove();
 +                    return true;
 +                }
 +            }
 +            return false;
 +        } finally {
 +            mDataLock.unlock();
 +        }
 +    }
 +
 +    public Repository getRootRepository() {
 +        return mRepo;
 +    }
 +
 +    public boolean isPropertySupported(String propertyName) {
 +        return StorableIntrospector.examine(mType)
 +            .getAllProperties().containsKey(propertyName);
 +    }
 +
 +    public Trigger<? super S> getInsertTrigger() {
 +        return null;
 +    }
 +
 +    public Trigger<? super S> getUpdateTrigger() {
 +        return null;
 +    }
 +
 +    public Trigger<? super S> getDeleteTrigger() {
 +        return null;
 +    }
 +
 +    public SequenceValueProducer getSequenceValueProducer(String name) throws PersistException {
 +        try {
 +            return mRepo.getSequenceValueProducer(name);
 +        } catch (RepositoryException e) {
 +            throw e.toPersistException();
 +        }
 +    }
 +
 +    public static interface InstanceFactory {
 +        Storable instantiate(ToyStorage storage);
 +    }
 +
 +    private class ToyQuery extends StandardQuery<S> {
 +        ToyQuery(FilterValues<S> values, OrderingList<S> ordering, QueryExecutor<S> executor) {
 +            super(values, ordering, executor);
 +        }
 +
 +        protected Transaction enterTransaction(IsolationLevel level) {
 +            return mRepo.enterTransaction(level);
 +        }
 +
 +        protected QueryFactory<S> queryFactory() {
 +            return ToyStorage.this;
 +        }
 +
 +        protected QueryExecutorFactory<S> executorFactory() {
 +            return ToyStorage.this;
 +        }
 +
 +        protected StandardQuery<S> newInstance(FilterValues<S> values,
 +                                               OrderingList<S> ordering,
 +                                               QueryExecutor<S> executor)
 +        {
 +            return new ToyQuery(values, ordering, executor);
 +        }
 +    }
 +}
 diff --git a/src/test/java/com/amazon/carbonado/repo/toy/ToyTransaction.java b/src/test/java/com/amazon/carbonado/repo/toy/ToyTransaction.java new file mode 100644 index 0000000..c16d1f1 --- /dev/null +++ b/src/test/java/com/amazon/carbonado/repo/toy/ToyTransaction.java @@ -0,0 +1,51 @@ +/*
 + * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
 + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
 + * of Amazon Technologies, Inc. or its affiliates.  All rights reserved.
 + *
 + * Licensed under the Apache License, Version 2.0 (the "License");
 + * you may not use this file except in compliance with the License.
 + * You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +package com.amazon.carbonado.repo.toy;
 +
 +import java.util.concurrent.TimeUnit;
 +
 +import com.amazon.carbonado.IsolationLevel;
 +import com.amazon.carbonado.PersistException;
 +import com.amazon.carbonado.Transaction;
 +
 +/**
 + *
 + * @author Brian S O'Neill
 + */
 +public class ToyTransaction implements Transaction {
 +    public void commit() throws PersistException {
 +    }
 +
 +    public void exit() throws PersistException {
 +    }
 +
 +    public void setForUpdate(boolean forUpdate) {
 +    }
 +
 +    public boolean isForUpdate() {
 +        return false;
 +    }
 +
 +    public void setDesiredLockTimeout(int timeout, TimeUnit unit) {
 +    }
 +
 +    public IsolationLevel getIsolationLevel() {
 +        throw new UnsupportedOperationException();
 +    }
 +}
 diff --git a/src/test/java/com/amazon/carbonado/repo/toy/package-info.java b/src/test/java/com/amazon/carbonado/repo/toy/package-info.java new file mode 100644 index 0000000..769ea8b --- /dev/null +++ b/src/test/java/com/amazon/carbonado/repo/toy/package-info.java @@ -0,0 +1,25 @@ +/*
 + * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
 + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
 + * of Amazon Technologies, Inc. or its affiliates.  All rights reserved.
 + *
 + * Licensed under the Apache License, Version 2.0 (the "License");
 + * you may not use this file except in compliance with the License.
 + * You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +/**
 + * Standalone toy repository implementation. This repository is only suitable
 + * for running tests that don't require anything sophisticated. It doesn't
 + * support transactions, nothing is actually persisted, and all queries do full
 + * scans. The repository is thread-safe, however.
 + */
 +package com.amazon.carbonado.repo.toy;
  | 
