summaryrefslogtreecommitdiff
path: root/src/test/java/com/amazon/carbonado/repo
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/amazon/carbonado/repo')
-rw-r--r--src/test/java/com/amazon/carbonado/repo/toy/ToyRepository.java106
-rw-r--r--src/test/java/com/amazon/carbonado/repo/toy/ToyStorableGenerator.java143
-rw-r--r--src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java242
-rw-r--r--src/test/java/com/amazon/carbonado/repo/toy/ToyTransaction.java51
-rw-r--r--src/test/java/com/amazon/carbonado/repo/toy/package-info.java25
5 files changed, 567 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..dd29e4b
--- /dev/null
+++ b/src/test/java/com/amazon/carbonado/repo/toy/ToyStorage.java
@@ -0,0 +1,242 @@
+/*
+ * 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.FilteredQueryExecutor;
+import com.amazon.carbonado.qe.IterableQueryExecutor;
+import com.amazon.carbonado.qe.QueryExecutor;
+import com.amazon.carbonado.qe.SortedQueryExecutor;
+import com.amazon.carbonado.qe.StandardQuery;
+
+/**
+ *
+ * @author Brian S O'Neill
+ */
+public class ToyStorage<S extends Storable> implements Storage<S>, MasterSupport<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() throws FetchException {
+ return new ToyQuery(null);
+ }
+
+ public Query<S> query(String filter) throws FetchException {
+ return query(Filter.filterFor(mType, filter));
+ }
+
+ public Query<S> query(Filter<S> filter) throws FetchException {
+ return new ToyQuery(filter.initialFilterValues());
+ }
+
+ 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)) {
+ existing.markAllPropertiesDirty();
+ storable.copyAllProperties(existing);
+ existing.markAllPropertiesClean();
+ 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, String... orderings) {
+ super(values, orderings);
+ }
+
+ protected Storage<S> getStorage() {
+ return ToyStorage.this;
+ }
+
+ protected Transaction enterTransactionForDelete(IsolationLevel level) {
+ return mRepo.enterTransaction(level);
+ }
+
+ protected QueryExecutor<S> getExecutor(FilterValues<S> values, String... orderings) {
+ QueryExecutor<S> executor = new IterableQueryExecutor<S>(mType, mData, mDataLock);
+
+ if (values != null) {
+ executor = new FilteredQueryExecutor<S>(executor, values.getFilter());
+ }
+
+ // FIXME: sorting
+
+ return executor;
+ }
+
+ protected StandardQuery<S> newInstance(FilterValues<S> values, String... orderings) {
+ return new ToyQuery(values, orderings);
+ }
+ }
+}
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;