You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by to...@apache.org on 2015/03/31 19:35:31 UTC

[1/2] incubator-usergrid git commit: Implemented new row key for unique values.

Repository: incubator-usergrid
Updated Branches:
  refs/heads/USERGRID-509 6e3fab6e4 -> d145eb4b8


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1ImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1ImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1ImplTest.java
new file mode 100644
index 0000000..40431d1
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1ImplTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.usergrid.persistence.collection.serialization.impl;
+
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
+import org.apache.usergrid.persistence.core.test.ITRunner;
+import org.apache.usergrid.persistence.core.test.UseModules;
+
+import com.google.inject.Inject;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+
+import static org.junit.Assert.assertEquals;
+
+
+@RunWith( ITRunner.class )
+@UseModules( TestCollectionModule.class )
+public class UniqueValueSerializationStrategyV1ImplTest extends UniqueValueSerializationStrategyImplTest {
+
+    @Inject
+    private UniqueValueSerializationStrategyV1Impl strategy;
+
+
+    /**
+     * Get the unique value serialization
+     */
+    protected UniqueValueSerializationStrategy getUniqueSerializationStrategy() {
+        return strategy;
+    }
+
+
+    @Test
+    public void testVersion() throws ConnectionException, InterruptedException {
+
+        assertEquals( CollectionDataVersions.INITIAL.getVersion(), strategy.getImplementationVersion() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2ImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2ImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2ImplTest.java
new file mode 100644
index 0000000..8de52fd
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2ImplTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.usergrid.persistence.collection.serialization.impl;
+
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
+import org.apache.usergrid.persistence.core.test.ITRunner;
+import org.apache.usergrid.persistence.core.test.UseModules;
+
+import com.google.inject.Inject;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+
+import static org.junit.Assert.assertEquals;
+
+
+@RunWith( ITRunner.class )
+@UseModules( TestCollectionModule.class )
+public class UniqueValueSerializationStrategyV2ImplTest extends UniqueValueSerializationStrategyImplTest {
+
+    @Inject
+    private UniqueValueSerializationStrategyV2Impl strategy;
+
+
+    /**
+     * Get the unique value serialization
+     */
+    protected UniqueValueSerializationStrategy getUniqueSerializationStrategy() {
+        return strategy;
+    }
+
+
+    @Test
+    public void testVersion() throws ConnectionException, InterruptedException {
+
+        assertEquals( CollectionDataVersions.LOG_REMOVAL.getVersion(), strategy.getImplementationVersion() );
+    }
+}


[2/2] incubator-usergrid git commit: Implemented new row key for unique values.

Posted by to...@apache.org.
Implemented new row key for unique values.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/d145eb4b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/d145eb4b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/d145eb4b

Branch: refs/heads/USERGRID-509
Commit: d145eb4b8e97c2eb4cb02fa568f357e5f8e7c5e2
Parents: 6e3fab6
Author: Todd Nine <tn...@apigee.com>
Authored: Tue Mar 31 11:35:31 2015 -0600
Committer: Todd Nine <tn...@apigee.com>
Committed: Tue Mar 31 11:35:31 2015 -0600

----------------------------------------------------------------------
 .../collection/guice/CollectionModule.java      |   1 -
 .../UniqueValueSerializationStrategy.java       |  10 +-
 .../impl/CollectionDataVersions.java            |  10 +
 ...vccEntitySerializationStrategyProxyImpl.java |   2 +
 .../MvccLogEntrySerializationProxyImpl.java     |   2 +
 .../MvccLogEntrySerializationStrategyImpl.java  |  10 -
 .../serialization/impl/SerializationModule.java |  48 ++-
 .../UniqueValueSerializationStrategyImpl.java   | 190 +++++-----
 ...iqueValueSerializationStrategyProxyImpl.java | 179 ++++++++++
 .../UniqueValueSerializationStrategyV1Impl.java | 159 +++++++++
 .../UniqueValueSerializationStrategyV2Impl.java | 139 ++++++++
 ...niqueValueSerializationStrategyImplTest.java | 330 ------------------
 ...niqueValueSerializationStrategyImplTest.java | 344 +++++++++++++++++++
 ...ValueSerializationStrategyProxyImplTest.java | 100 ++++++
 ...queValueSerializationStrategyV1ImplTest.java |  57 +++
 ...queValueSerializationStrategyV2ImplTest.java |  58 ++++
 16 files changed, 1197 insertions(+), 442 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/guice/CollectionModule.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/guice/CollectionModule.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/guice/CollectionModule.java
index eaf89ef..b256a44 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/guice/CollectionModule.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/guice/CollectionModule.java
@@ -76,7 +76,6 @@ public abstract class CollectionModule extends AbstractModule {
         //bind this to our factory
         install( new GuicyFigModule( EntityCacheFig.class ) );
 
-        bind( UniqueValueSerializationStrategy.class ).to( UniqueValueSerializationStrategyImpl.class );
         bind( ChangeLogGenerator.class).to( ChangeLogGeneratorImpl.class);
 
         configureMigrationProvider();

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
index 71af460..3645107 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/UniqueValueSerializationStrategy.java
@@ -21,6 +21,7 @@ package org.apache.usergrid.persistence.collection.serialization;
 import java.util.Collection;
 import java.util.Iterator;
 
+import org.apache.usergrid.persistence.core.migration.data.VersionedData;
 import org.apache.usergrid.persistence.core.migration.schema.Migration;
 import org.apache.usergrid.persistence.core.scope.ApplicationScope;
 import org.apache.usergrid.persistence.model.entity.Id;
@@ -34,7 +35,7 @@ import com.netflix.astyanax.model.ConsistencyLevel;
 /**
  * Reads and writes to UniqueValues column family.
  */
-public interface UniqueValueSerializationStrategy extends Migration {
+public interface UniqueValueSerializationStrategy extends Migration, VersionedData {
 
 
     /**
@@ -73,14 +74,14 @@ public interface UniqueValueSerializationStrategy extends Migration {
     /**
     * Load UniqueValue that matches field from collection or null if that value does not exist.
     *
-    * @param colScope Collection scope in which to look for field name/value
+    * @param applicationScope Collection scope in which to look for field name/value
     * @param consistencyLevel Consistency level of query
     * @param type The type the unique value exists within
     * @param fields Field name/value to search for
     * @return UniqueValueSet containing fields from the collection that exist in cassandra
     * @throws ConnectionException on error connecting to Cassandra
     */
-    UniqueValueSet load( ApplicationScope colScope, ConsistencyLevel consistencyLevel, String type,
+    UniqueValueSet load( ApplicationScope applicationScope, ConsistencyLevel consistencyLevel, String type,
                          Collection<Field> fields ) throws ConnectionException;
 
 
@@ -98,10 +99,11 @@ public interface UniqueValueSerializationStrategy extends Migration {
     /**
      * Delete the specified Unique Value from Cassandra.
      *
+     * @param applicationScope The scope of the application
      * @param uniqueValue Object to be deleted.
      * @return MutatationBatch that encapsulates operation, caller may or may not execute.
      */
-    MutationBatch delete( ApplicationScope scope, UniqueValue uniqueValue );
+    MutationBatch delete( ApplicationScope applicationScope, UniqueValue uniqueValue );
 
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/CollectionDataVersions.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/CollectionDataVersions.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/CollectionDataVersions.java
index 84028d6..b1ce98b 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/CollectionDataVersions.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/CollectionDataVersions.java
@@ -28,8 +28,18 @@ package org.apache.usergrid.persistence.collection.serialization.impl;
  * Versions of data as they exist across our system
  */
 public enum CollectionDataVersions{
+    /**
+     * The initial released version
+     */
     INITIAL(0),
+    /**
+     * The version where serialization was changed from using a short in the composite to an integer
+     */
     BUFFER_SHORT_FIX(1),
+
+    /**
+     * The change where we move unique field versions to their own  CF, and then only store our latest object version
+     */
     LOG_REMOVAL(2);
 
     private final int version;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccEntitySerializationStrategyProxyImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccEntitySerializationStrategyProxyImpl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccEntitySerializationStrategyProxyImpl.java
index bb143a4..b45f68b 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccEntitySerializationStrategyProxyImpl.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccEntitySerializationStrategyProxyImpl.java
@@ -35,6 +35,7 @@ import org.apache.usergrid.persistence.model.entity.Id;
 
 import com.google.common.base.Optional;
 import com.google.inject.Inject;
+import com.google.inject.Singleton;
 import com.netflix.astyanax.Keyspace;
 import com.netflix.astyanax.MutationBatch;
 
@@ -44,6 +45,7 @@ import com.netflix.astyanax.MutationBatch;
  * migration data goes to both sources and is read from the old source. After the upgrade completes,
  * it will be available from the new source
  */
+@Singleton
 public class MvccEntitySerializationStrategyProxyImpl implements MvccEntitySerializationStrategy {
 
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationProxyImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationProxyImpl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationProxyImpl.java
index e0f6f03..81c0248 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationProxyImpl.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationProxyImpl.java
@@ -37,6 +37,7 @@ import org.apache.usergrid.persistence.core.scope.ApplicationScope;
 import org.apache.usergrid.persistence.model.entity.Id;
 
 import com.google.inject.Inject;
+import com.google.inject.Singleton;
 import com.netflix.astyanax.Keyspace;
 import com.netflix.astyanax.MutationBatch;
 
@@ -44,6 +45,7 @@ import com.netflix.astyanax.MutationBatch;
 /**
  * The proxy for performing log entry serialization
  */
+@Singleton
 public class MvccLogEntrySerializationProxyImpl implements MvccLogEntrySerializationStrategy {
 
     protected final Keyspace keyspace;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationStrategyImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationStrategyImpl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationStrategyImpl.java
index d6baa3c..76e9dba 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationStrategyImpl.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/MvccLogEntrySerializationStrategyImpl.java
@@ -273,18 +273,8 @@ public abstract class MvccLogEntrySerializationStrategyImpl<K> implements MvccLo
         LOG.debug( "Writing version with timestamp '{}'", timestamp );
 
         final Id applicationId = collectionScope.getApplication();
-        final Id ownerId = applicationId;
-        final String collectionName = LegacyScopeUtils.getCollectionScopeNameFromEntityType( entityId.getType() );
 
         final ScopedRowKey<K> key = createKey( applicationId, entityId );
-//
-//        final CollectionPrefixedKey<Id> collectionPrefixedKey =
-//                new CollectionPrefixedKey<>( collectionName, ownerId, entityId );
-//
-//
-//        final ScopedRowKey<CollectionPrefixedKey<Id>> rowKey =
-//                ScopedRowKey.fromKey( applicationId, collectionPrefixedKey );
-
 
         op.doOp( batch.withRow( CF_ENTITY_LOG, key ) );
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/SerializationModule.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/SerializationModule.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/SerializationModule.java
index fa1991a..bd2728b 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/SerializationModule.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/SerializationModule.java
@@ -67,21 +67,28 @@ public class SerializationModule extends AbstractModule {
         bind( MvccLogEntrySerializationStrategyV2Impl.class );
 
 
-        bind( MvccLogEntrySerializationStrategy.class )
-                                                       .to( MvccLogEntrySerializationProxyImpl.class );
+        bind( MvccLogEntrySerializationStrategy.class ).to( MvccLogEntrySerializationProxyImpl.class );
 
 
-        bind( UniqueValueSerializationStrategy.class ).to( UniqueValueSerializationStrategyImpl.class );
+        bind( UniqueValueSerializationStrategyV1Impl.class );
+        bind(UniqueValueSerializationStrategyV2Impl.class);
+
+        bind( UniqueValueSerializationStrategy.class ).to( UniqueValueSerializationStrategyProxyImpl.class );
 
         //do multibindings for migrations
         Multibinder<Migration> migrationBinder = Multibinder.newSetBinder( binder(), Migration.class );
+        //entity serialization versions
         migrationBinder.addBinding().to( Key.get( MvccEntitySerializationStrategyV1Impl.class ) );
         migrationBinder.addBinding().to( Key.get( MvccEntitySerializationStrategyV2Impl.class ) );
         migrationBinder.addBinding().to( Key.get( MvccEntitySerializationStrategyV3Impl.class ) );
+
+        //log serialization versions
         migrationBinder.addBinding().to( Key.get( MvccLogEntrySerializationStrategyV1Impl.class ) );
         migrationBinder.addBinding().to( Key.get( MvccLogEntrySerializationStrategyV2Impl.class ) );
 
-        migrationBinder.addBinding().to( Key.get( UniqueValueSerializationStrategy.class ) );
+        //unique value serialization versions
+        migrationBinder.addBinding().to( Key.get( UniqueValueSerializationStrategyV1Impl.class ) );
+        migrationBinder.addBinding().to( Key.get( UniqueValueSerializationStrategyV2Impl.class ) );
 
 
         //bind our settings as an eager singleton so it's checked on startup
@@ -123,7 +130,7 @@ public class SerializationModule extends AbstractModule {
         //note that we MUST migrate to v3 before our next migration, if v4 and v5 is implemented we will need a
         // v3->v5 and a v4->v5 set
         MigrationRelationship<MvccEntitySerializationStrategy> current =
-            new MigrationRelationship<MvccEntitySerializationStrategy>( v3, v3 );
+            new MigrationRelationship<>( v3, v3 );
 
 
         //now create our set of versions
@@ -151,7 +158,7 @@ public class SerializationModule extends AbstractModule {
         //note that we MUST migrate to v3 before our next migration, if v4 and v5 is implemented we will need a
         // v3->v5 and a v4->v5 set
         MigrationRelationship<MvccLogEntrySerializationStrategy> current =
-            new MigrationRelationship<MvccLogEntrySerializationStrategy>( v2, v2 );
+            new MigrationRelationship<>( v2, v2 );
 
 
         //now create our set of versions
@@ -160,4 +167,33 @@ public class SerializationModule extends AbstractModule {
 
         return set;
     }
+
+
+
+    /**
+     * Configure via explicit declaration the migration path we can follow
+     */
+    @Singleton
+    @Inject
+    @Provides
+    public VersionedMigrationSet<UniqueValueSerializationStrategy> getVersions(
+        final UniqueValueSerializationStrategyV1Impl v1, final UniqueValueSerializationStrategyV2Impl v2) {
+
+
+        //we must perform a migration from v1 to v3 in order to maintain consistency
+        MigrationRelationship<UniqueValueSerializationStrategy> v1Tov2 = new MigrationRelationship<>( v1, v2 );
+
+
+        //note that we MUST migrate to v3 before our next migration, if v4 and v5 is implemented we will need a
+        // v3->v5 and a v4->v5 set
+        MigrationRelationship<UniqueValueSerializationStrategy> current =
+            new MigrationRelationship<>( v2, v2 );
+
+
+        //now create our set of versions
+        VersionedMigrationSet<UniqueValueSerializationStrategy> set =
+            new VersionedMigrationSet<>( v1Tov2, current );
+
+        return set;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
index bd35c7a..a1fb4cc 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImpl.java
@@ -39,7 +39,6 @@ import org.apache.usergrid.persistence.core.astyanax.CassandraFig;
 import org.apache.usergrid.persistence.core.astyanax.ColumnNameIterator;
 import org.apache.usergrid.persistence.core.astyanax.ColumnParser;
 import org.apache.usergrid.persistence.core.astyanax.ColumnTypes;
-import org.apache.usergrid.persistence.core.astyanax.IdRowCompositeSerializer;
 import org.apache.usergrid.persistence.core.astyanax.MultiTennantColumnFamily;
 import org.apache.usergrid.persistence.core.astyanax.MultiTennantColumnFamilyDefinition;
 import org.apache.usergrid.persistence.core.astyanax.ScopedRowKey;
@@ -64,53 +63,42 @@ import com.netflix.astyanax.util.RangeBuilder;
 /**
  * Reads and writes to UniqueValues column family.
  */
-public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializationStrategy {
+public abstract class UniqueValueSerializationStrategyImpl<FieldKey, EntityKey>
+    implements UniqueValueSerializationStrategy {
 
     private static final Logger log = LoggerFactory.getLogger( UniqueValueSerializationStrategyImpl.class );
 
 
-    private static final CollectionScopedRowKeySerializer<Field> ROW_KEY_SER =
-        new CollectionScopedRowKeySerializer<>( UniqueFieldRowKeySerializer.get() );
+    private final MultiTennantColumnFamily<ScopedRowKey<FieldKey>, EntityVersion>
+        CF_UNIQUE_VALUES;
 
-    private static final EntityVersionSerializer ENTITY_VERSION_SER = new EntityVersionSerializer();
 
-    private static final MultiTennantColumnFamily<ScopedRowKey<CollectionPrefixedKey<Field>>, EntityVersion>
-        CF_UNIQUE_VALUES = new MultiTennantColumnFamily<>( "Unique_Values", ROW_KEY_SER, ENTITY_VERSION_SER );
-
-
-
-    private static final IdRowCompositeSerializer ID_SER = IdRowCompositeSerializer.get();
-
-
-    private static final CollectionScopedRowKeySerializer<Id> ENTITY_ROW_KEY_SER =
-        new CollectionScopedRowKeySerializer<>( ID_SER );
-
-
-
-    private static final MultiTennantColumnFamily<ScopedRowKey<CollectionPrefixedKey<Id>>, UniqueFieldEntry>
-        CF_ENTITY_UNIQUE_VALUES =
-        new MultiTennantColumnFamily<>( "Entity_Unique_Values", ENTITY_ROW_KEY_SER, UniqueFieldEntrySerializer.get() );
+    private final MultiTennantColumnFamily<ScopedRowKey<EntityKey>, UniqueFieldEntry>
+        CF_ENTITY_UNIQUE_VALUE_LOG ;
 
     public static final int COL_VALUE = 0x0;
 
 
     private final SerializationFig serializationFig;
     protected final Keyspace keyspace;
-       private final CassandraFig cassandraFig;
-
+    private final CassandraFig cassandraFig;
 
 
     /**
      * Construct serialization strategy for keyspace.
      *
      * @param keyspace Keyspace in which to store Unique Values.
-     * @param serializationFig
+     * @param cassandraFig The cassandra configuration
+     * @param serializationFig The serialization configuration
      */
-    @Inject
-    public UniqueValueSerializationStrategyImpl( final Keyspace keyspace, final CassandraFig cassandraFig, final  SerializationFig serializationFig ) {
+    public UniqueValueSerializationStrategyImpl( final Keyspace keyspace, final CassandraFig cassandraFig,
+                                                 final SerializationFig serializationFig ) {
         this.keyspace = keyspace;
         this.cassandraFig = cassandraFig;
         this.serializationFig = serializationFig;
+
+        CF_UNIQUE_VALUES = getUniqueValuesCF();
+        CF_ENTITY_UNIQUE_VALUE_LOG = getEntityUniqueLogCF();
     }
 
 
@@ -131,7 +119,7 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
         final EntityVersion ev = new EntityVersion( entityId, entityVersion );
         final UniqueFieldEntry uniqueFieldEntry = new UniqueFieldEntry( entityVersion, field );
 
-        return doWrite( collectionScope, value, new UniqueValueSerializationStrategyImpl.RowOp() {
+        return doWrite( collectionScope, value, new RowOp() {
 
             @Override
             public void doLookup( final ColumnListMutation<EntityVersion> colMutation ) {
@@ -148,7 +136,8 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
 
 
     @Override
-    public MutationBatch write( final ApplicationScope collectionScope, final UniqueValue value, final int timeToLive ) {
+    public MutationBatch write( final ApplicationScope collectionScope, final UniqueValue value,
+                                final int timeToLive ) {
 
         Preconditions.checkNotNull( value, "value is required" );
         Preconditions.checkArgument( timeToLive > 0, "timeToLive must be greater than 0 is required" );
@@ -163,7 +152,7 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
         final EntityVersion ev = new EntityVersion( entityId, entityVersion );
         final UniqueFieldEntry uniqueFieldEntry = new UniqueFieldEntry( entityVersion, field );
 
-        return doWrite( collectionScope, value, new UniqueValueSerializationStrategyImpl.RowOp() {
+        return doWrite( collectionScope, value, new RowOp() {
 
             @Override
             public void doLookup( final ColumnListMutation<EntityVersion> colMutation ) {
@@ -198,7 +187,7 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
         final EntityVersion ev = new EntityVersion( entityId, entityVersion );
         final UniqueFieldEntry uniqueFieldEntry = new UniqueFieldEntry( entityVersion, field );
 
-        return doWrite( scope, value, new UniqueValueSerializationStrategyImpl.RowOp() {
+        return doWrite( scope, value, new RowOp() {
 
             @Override
             public void doLookup( final ColumnListMutation<EntityVersion> colMutation ) {
@@ -225,32 +214,24 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
         final MutationBatch batch = keyspace.prepareMutationBatch();
 
         final Id applicationId = applicationScope.getApplication();
-        final Id uniqueValueId = uniqueValue.getEntityId();
 
-        final String collectionName = LegacyScopeUtils.getCollectionScopeNameFromEntityType( uniqueValueId.getType() );
+        final FieldKey fieldKey = createUniqueValueKey( applicationId, uniqueValue.getEntityId().getType(), uniqueValue.getField() );
 
-        final CollectionPrefixedKey<Field> uniquePrefixedKey =
-            new CollectionPrefixedKey<>( collectionName, applicationId, uniqueValue.getField() );
 
+        op.doLookup( batch.withRow( CF_UNIQUE_VALUES, ScopedRowKey.fromKey( applicationId, fieldKey ) ) );
 
-        op.doLookup( batch
-            .withRow( CF_UNIQUE_VALUES, ScopedRowKey.fromKey( applicationId, uniquePrefixedKey ) ) );
 
+        final EntityKey entityKey = createEntityUniqueLogKey( applicationId, uniqueValue.getEntityId() );
 
-        final Id ownerId = applicationId;
+        op.doLog( batch.withRow( CF_ENTITY_UNIQUE_VALUE_LOG,
+            ScopedRowKey.fromKey( applicationId, entityKey ) ) );
 
-        final CollectionPrefixedKey<Id> collectionPrefixedEntityKey =
-            new CollectionPrefixedKey<>( collectionName, ownerId, uniqueValue.getEntityId() );
 
-
-        op.doLog( batch.withRow( CF_ENTITY_UNIQUE_VALUES,
-            ScopedRowKey.fromKey( applicationId, collectionPrefixedEntityKey ) ) );
-
-
-        if(log.isDebugEnabled()) {
-            log.debug( "Writing unique value collectionScope={} id={} version={} name={} value={} ttl={} ", new
-                Object[] {
-                    collectionName, uniqueValueId, uniqueValue.getEntityVersion(), uniqueValue.getField().getName(), uniqueValue.getField().getValue()
+        if ( log.isDebugEnabled() ) {
+            log.debug( "Writing unique value version={} name={} value={} ",
+                new Object[] {
+                    uniqueValue.getEntityVersion(), uniqueValue.getField().getName(),
+                    uniqueValue.getField().getValue()
                 } );
         }
 
@@ -259,64 +240,64 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
     }
 
 
-
     @Override
-    public UniqueValueSet load(final ApplicationScope colScope, final String type, final Collection<Field> fields ) throws ConnectionException{
-        return load(colScope,ConsistencyLevel.valueOf(cassandraFig.getReadCL()), type, fields);
+    public UniqueValueSet load( final ApplicationScope colScope, final String type, final Collection<Field> fields )
+        throws ConnectionException {
+        return load( colScope, ConsistencyLevel.valueOf( cassandraFig.getReadCL() ), type, fields );
     }
 
+
     @Override
-    public UniqueValueSet load(final ApplicationScope appScope, final ConsistencyLevel consistencyLevel,  final String type,  final Collection<Field> fields )
-            throws ConnectionException {
+    public UniqueValueSet load( final ApplicationScope appScope, final ConsistencyLevel consistencyLevel,
+                                final String type, final Collection<Field> fields ) throws ConnectionException {
 
         Preconditions.checkNotNull( fields, "fields are required" );
         Preconditions.checkArgument( fields.size() > 0, "More than 1 field must be specified" );
 
 
-        final List<ScopedRowKey<CollectionPrefixedKey<Field>>> keys = new ArrayList<>( fields.size() );
+        final List<ScopedRowKey<FieldKey>> keys = new ArrayList<>( fields.size() );
 
         final Id applicationId = appScope.getApplication();
-        final Id ownerId = appScope.getApplication();
-        final String collectionName = LegacyScopeUtils.getCollectionScopeNameFromEntityType( type );
 
         for ( Field field : fields ) {
 
-            final CollectionPrefixedKey<Field> collectionPrefixedKey = new CollectionPrefixedKey<>( collectionName, ownerId, field );
+            final FieldKey key = createUniqueValueKey( applicationId, type,  field );
 
 
-            final ScopedRowKey<CollectionPrefixedKey<Field>> rowKey = ScopedRowKey.fromKey(applicationId, collectionPrefixedKey );
+            final ScopedRowKey<FieldKey> rowKey =
+                ScopedRowKey.fromKey( applicationId, key );
 
             keys.add( rowKey );
         }
 
         final UniqueValueSetImpl uniqueValueSet = new UniqueValueSetImpl( fields.size() );
 
-        Iterator<Row<ScopedRowKey<CollectionPrefixedKey<Field>>, EntityVersion>> results =
-                keyspace.prepareQuery( CF_UNIQUE_VALUES ).setConsistencyLevel(consistencyLevel).getKeySlice( keys )
-                        .withColumnRange( new RangeBuilder().setLimit( 1 ).build() ).execute().getResult().iterator();
+        Iterator<Row<ScopedRowKey<FieldKey>, EntityVersion>> results =
+            keyspace.prepareQuery( CF_UNIQUE_VALUES ).setConsistencyLevel( consistencyLevel ).getKeySlice( keys )
+                    .withColumnRange( new RangeBuilder().setLimit( 1 ).build() ).execute().getResult().iterator();
 
 
         while ( results.hasNext() )
 
         {
 
-            final Row<ScopedRowKey<CollectionPrefixedKey<Field>>, EntityVersion> unique = results.next();
+            final Row<ScopedRowKey<FieldKey>, EntityVersion> unique = results.next();
 
 
-            final Field field = unique.getKey().getKey().getSubKey();
+            final Field field = parseRowKey( unique.getKey() );
 
             final Iterator<Column<EntityVersion>> columnList = unique.getColumns().iterator();
 
             //sanity check, nothing to do, skip it
-            if ( !columnList.hasNext()) {
+            if ( !columnList.hasNext() ) {
                 continue;
             }
 
             final EntityVersion entityVersion = columnList.next().getName();
 
 
-            final UniqueValueImpl uniqueValue = new UniqueValueImpl(field, entityVersion.getEntityId(),
-                    entityVersion.getEntityVersion() );
+            final UniqueValueImpl uniqueValue =
+                new UniqueValueImpl( field, entityVersion.getEntityId(), entityVersion.getEntityVersion() );
 
             uniqueValueSet.addValue( uniqueValue );
         }
@@ -327,53 +308,44 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
 
     @Override
     public Iterator<UniqueValue> getAllUniqueFields( final ApplicationScope collectionScope, final Id entityId ) {
-
-
         Preconditions.checkNotNull( collectionScope, "collectionScope is required" );
         Preconditions.checkNotNull( entityId, "entity id is required" );
 
 
         final Id applicationId = collectionScope.getApplication();
-        final Id ownerId = applicationId;
-        final String collectionName = LegacyScopeUtils.getCollectionScopeNameFromEntityType( entityId.getType() );
 
-        final CollectionPrefixedKey<Id> collectionPrefixedKey =
-                new CollectionPrefixedKey<>( collectionName, ownerId, entityId );
+        final EntityKey entityKey = createEntityUniqueLogKey( applicationId, entityId );
 
 
-        final ScopedRowKey<CollectionPrefixedKey<Id>> rowKey =
-                ScopedRowKey.fromKey( applicationId, collectionPrefixedKey );
+        final ScopedRowKey<EntityKey> rowKey =
+            ScopedRowKey.fromKey( applicationId, entityKey );
 
 
-        RowQuery<ScopedRowKey<CollectionPrefixedKey<Id>>, UniqueFieldEntry> query =
-                keyspace.prepareQuery( CF_ENTITY_UNIQUE_VALUES ).getKey( rowKey ).withColumnRange(
-                    ( UniqueFieldEntry ) null, null, false, serializationFig.getBufferSize() );
+        RowQuery<ScopedRowKey<EntityKey>, UniqueFieldEntry> query =
+            keyspace.prepareQuery( CF_ENTITY_UNIQUE_VALUE_LOG ).getKey( rowKey )
+                    .withColumnRange( ( UniqueFieldEntry ) null, null, false, serializationFig.getBufferSize() );
 
         return new ColumnNameIterator( query, new UniqueEntryParser( entityId ), false );
-
     }
 
 
     /**
      * Simple callback to perform puts and deletes with a common row setup code
      */
-    private static interface RowOp {
+    private interface RowOp {
 
         /**
          * Execute the mutation into the lookup CF_UNIQUE_VALUES row
-         * @param colMutation
          */
         void doLookup( ColumnListMutation<EntityVersion> colMutation );
 
         /**
          * Execute the mutation into the lCF_ENTITY_UNIQUE_VALUESLUE row
-         * @param colMutation
          */
-        void doLog( ColumnListMutation<UniqueFieldEntry> colMutation);
+        void doLog( ColumnListMutation<UniqueFieldEntry> colMutation );
     }
 
 
-
     /**
      * Converts raw columns to the expected output
      */
@@ -394,20 +366,56 @@ public class UniqueValueSerializationStrategyImpl implements UniqueValueSerializ
     }
 
 
-
     @Override
     public Collection<MultiTennantColumnFamilyDefinition> getColumnFamilies() {
 
         final MultiTennantColumnFamilyDefinition uniqueLookupCF =
-                new MultiTennantColumnFamilyDefinition( CF_UNIQUE_VALUES, BytesType.class.getSimpleName(),
-                        ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
-                        MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
+            new MultiTennantColumnFamilyDefinition( CF_UNIQUE_VALUES, BytesType.class.getSimpleName(),
+                ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
+                MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
 
         final MultiTennantColumnFamilyDefinition uniqueLogCF =
-                        new MultiTennantColumnFamilyDefinition( CF_ENTITY_UNIQUE_VALUES, BytesType.class.getSimpleName(),
-                                ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
-                                MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
+            new MultiTennantColumnFamilyDefinition( CF_ENTITY_UNIQUE_VALUE_LOG, BytesType.class.getSimpleName(),
+                ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
+                MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
 
-        return Arrays.asList( uniqueLookupCF, uniqueLogCF);
+        return Arrays.asList( uniqueLookupCF, uniqueLogCF );
     }
+
+
+    /**
+     * Get the column family for the unique fields
+     */
+    protected abstract MultiTennantColumnFamily<ScopedRowKey<FieldKey>, EntityVersion> getUniqueValuesCF();
+
+
+    /**
+     * Generate a key that is compatible with the column family
+     *
+     * @param applicationId The applicationId
+     * @param type The type in the field
+     * @param field The field we're creating the key for
+     */
+    protected abstract FieldKey createUniqueValueKey(final Id applicationId, final String type, final Field field );
+
+    /**
+     * Parse the row key into the field
+     * @param rowKey
+     * @return
+     */
+    protected abstract Field parseRowKey(final ScopedRowKey<FieldKey> rowKey);
+
+
+    /**
+     * Get the column family for the unique field CF
+     */
+    protected abstract MultiTennantColumnFamily<ScopedRowKey<EntityKey>, UniqueFieldEntry> getEntityUniqueLogCF();
+
+    /**
+     * Generate a key that is compatible with the column family
+     *
+     * @param applicationId The applicationId
+     * @param uniqueValueId The uniqueValue
+     */
+    protected abstract EntityKey createEntityUniqueLogKey(final Id applicationId,  final Id uniqueValueId );
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImpl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImpl.java
new file mode 100644
index 0000000..3b15142
--- /dev/null
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImpl.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.usergrid.persistence.collection.serialization.impl;
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.apache.usergrid.persistence.collection.serialization.UniqueValue;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValueSet;
+import org.apache.usergrid.persistence.collection.serialization.impl.migration.CollectionMigrationPlugin;
+import org.apache.usergrid.persistence.core.astyanax.MultiTennantColumnFamilyDefinition;
+import org.apache.usergrid.persistence.core.migration.data.MigrationInfoCache;
+import org.apache.usergrid.persistence.core.migration.data.MigrationRelationship;
+import org.apache.usergrid.persistence.core.migration.data.VersionedMigrationSet;
+import org.apache.usergrid.persistence.core.scope.ApplicationScope;
+import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.field.Field;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.netflix.astyanax.Keyspace;
+import com.netflix.astyanax.MutationBatch;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+import com.netflix.astyanax.model.ConsistencyLevel;
+
+
+@Singleton
+public class UniqueValueSerializationStrategyProxyImpl implements UniqueValueSerializationStrategy {
+
+
+    protected final Keyspace keyspace;
+    private final VersionedMigrationSet<UniqueValueSerializationStrategy> versions;
+    private final MigrationInfoCache migrationInfoCache;
+
+
+    @Inject
+    public UniqueValueSerializationStrategyProxyImpl( final Keyspace keyspace,
+                                                      final VersionedMigrationSet<UniqueValueSerializationStrategy>
+                                                          allVersions,
+                                                      final MigrationInfoCache migrationInfoCache ) {
+
+        this.keyspace = keyspace;
+        this.migrationInfoCache = migrationInfoCache;
+        this.versions = allVersions;
+    }
+
+
+    @Override
+    public MutationBatch write( final ApplicationScope applicationScope, final UniqueValue uniqueValue ) {
+        final MigrationRelationship<UniqueValueSerializationStrategy> migration = getMigrationRelationShip();
+
+        if ( migration.needsMigration() ) {
+            final MutationBatch aggregateBatch = keyspace.prepareMutationBatch();
+
+            aggregateBatch.mergeShallow( migration.from.write( applicationScope, uniqueValue ) );
+            aggregateBatch.mergeShallow( migration.to.write( applicationScope, uniqueValue ) );
+
+            return aggregateBatch;
+        }
+
+        return migration.to.write( applicationScope, uniqueValue );
+    }
+
+
+    @Override
+    public MutationBatch write( final ApplicationScope applicationScope, final UniqueValue uniqueValue,
+                                final int timeToLive ) {
+        final MigrationRelationship<UniqueValueSerializationStrategy> migration = getMigrationRelationShip();
+
+        if ( migration.needsMigration() ) {
+            final MutationBatch aggregateBatch = keyspace.prepareMutationBatch();
+
+            aggregateBatch.mergeShallow( migration.from.write( applicationScope, uniqueValue, timeToLive ) );
+            aggregateBatch.mergeShallow( migration.to.write( applicationScope, uniqueValue, timeToLive ) );
+
+            return aggregateBatch;
+        }
+
+        return migration.to.write( applicationScope, uniqueValue, timeToLive );
+    }
+
+
+    @Override
+    public UniqueValueSet load( final ApplicationScope applicationScope, final String type,
+                                final Collection<Field> fields ) throws ConnectionException {
+
+        final MigrationRelationship<UniqueValueSerializationStrategy> migration = getMigrationRelationShip();
+
+        if ( migration.needsMigration() ) {
+            return migration.from.load( applicationScope, type, fields );
+        }
+
+        return migration.to.load( applicationScope, type, fields );
+    }
+
+
+    @Override
+    public UniqueValueSet load( final ApplicationScope applicationScope, final ConsistencyLevel consistencyLevel,
+                                final String type, final Collection<Field> fields ) throws ConnectionException {
+
+        final MigrationRelationship<UniqueValueSerializationStrategy> migration = getMigrationRelationShip();
+
+        if ( migration.needsMigration() ) {
+            return migration.from.load( applicationScope, type, fields );
+        }
+
+        return migration.to.load( applicationScope, type, fields );
+    }
+
+
+    @Override
+    public Iterator<UniqueValue> getAllUniqueFields( final ApplicationScope applicationScope, final Id entityId ) {
+        final MigrationRelationship<UniqueValueSerializationStrategy> migration = getMigrationRelationShip();
+
+        if ( migration.needsMigration() ) {
+            return migration.from.getAllUniqueFields( applicationScope, entityId );
+        }
+
+        return migration.to.getAllUniqueFields( applicationScope, entityId );
+    }
+
+
+    @Override
+    public MutationBatch delete( final ApplicationScope applicationScope, final UniqueValue uniqueValue ) {
+        final MigrationRelationship<UniqueValueSerializationStrategy> migration = getMigrationRelationShip();
+
+        if ( migration.needsMigration() ) {
+            final MutationBatch aggregateBatch = keyspace.prepareMutationBatch();
+
+            aggregateBatch.mergeShallow( migration.from.delete( applicationScope, uniqueValue ) );
+            aggregateBatch.mergeShallow( migration.to.delete( applicationScope, uniqueValue ) );
+
+            return aggregateBatch;
+        }
+
+        return migration.to.delete( applicationScope, uniqueValue );
+    }
+
+
+    /**
+     * Return true if we're on an old version
+     */
+    private MigrationRelationship<UniqueValueSerializationStrategy> getMigrationRelationShip() {
+        return this.versions
+            .getMigrationRelationship( migrationInfoCache.getVersion( CollectionMigrationPlugin.PLUGIN_NAME ) );
+    }
+
+
+    @Override
+    public Collection<MultiTennantColumnFamilyDefinition> getColumnFamilies() {
+        return Collections.emptyList();
+    }
+
+
+    @Override
+    public int getImplementationVersion() {
+        throw new UnsupportedOperationException( "Not supported in the proxy" );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1Impl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1Impl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1Impl.java
new file mode 100644
index 0000000..6551f5d
--- /dev/null
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV1Impl.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.usergrid.persistence.collection.serialization.impl;
+
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.cassandra.db.marshal.BytesType;
+
+import org.apache.usergrid.persistence.collection.serialization.SerializationFig;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValue;
+import org.apache.usergrid.persistence.collection.serialization.impl.util.LegacyScopeUtils;
+import org.apache.usergrid.persistence.core.astyanax.CassandraFig;
+import org.apache.usergrid.persistence.core.astyanax.ColumnTypes;
+import org.apache.usergrid.persistence.core.astyanax.IdRowCompositeSerializer;
+import org.apache.usergrid.persistence.core.astyanax.MultiTennantColumnFamily;
+import org.apache.usergrid.persistence.core.astyanax.MultiTennantColumnFamilyDefinition;
+import org.apache.usergrid.persistence.core.astyanax.ScopedRowKey;
+import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.field.Field;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.netflix.astyanax.Keyspace;
+
+
+/**
+ * V1 impl with unique value serialization strategy with the collection scope
+ */
+@Singleton
+public class UniqueValueSerializationStrategyV1Impl  extends UniqueValueSerializationStrategyImpl<CollectionPrefixedKey<Field>, CollectionPrefixedKey<Id>> {
+
+
+    private static final CollectionScopedRowKeySerializer<Field> ROW_KEY_SER =
+        new CollectionScopedRowKeySerializer<>( UniqueFieldRowKeySerializer.get() );
+
+    private static final EntityVersionSerializer ENTITY_VERSION_SER = new EntityVersionSerializer();
+
+    private static final MultiTennantColumnFamily<ScopedRowKey<CollectionPrefixedKey<Field>>, EntityVersion>
+        CF_UNIQUE_VALUES = new MultiTennantColumnFamily<>( "Unique_Values", ROW_KEY_SER, ENTITY_VERSION_SER );
+
+
+    private static final IdRowCompositeSerializer ID_SER = IdRowCompositeSerializer.get();
+
+
+    private static final CollectionScopedRowKeySerializer<Id> ENTITY_ROW_KEY_SER =
+        new CollectionScopedRowKeySerializer<>( ID_SER );
+
+
+    private static final MultiTennantColumnFamily<ScopedRowKey<CollectionPrefixedKey<Id>>, UniqueFieldEntry>
+        CF_ENTITY_UNIQUE_VALUE_LOG =
+        new MultiTennantColumnFamily<>( "Entity_Unique_Values", ENTITY_ROW_KEY_SER, UniqueFieldEntrySerializer.get() );
+
+
+    /**
+     * Construct serialization strategy for keyspace.
+     *
+     * @param keyspace Keyspace in which to store Unique Values.
+     * @param cassandraFig The cassandra configuration
+     * @param serializationFig The serialization configuration
+     */
+    @Inject
+    public UniqueValueSerializationStrategyV1Impl( final Keyspace keyspace, final CassandraFig cassandraFig,
+                                                   final SerializationFig serializationFig ) {
+        super( keyspace, cassandraFig, serializationFig );
+    }
+
+
+    @Override
+    public Collection<MultiTennantColumnFamilyDefinition> getColumnFamilies() {
+
+        final MultiTennantColumnFamilyDefinition uniqueLookupCF =
+            new MultiTennantColumnFamilyDefinition( CF_UNIQUE_VALUES, BytesType.class.getSimpleName(),
+                ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
+                MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
+
+        final MultiTennantColumnFamilyDefinition uniqueLogCF =
+            new MultiTennantColumnFamilyDefinition( CF_ENTITY_UNIQUE_VALUE_LOG, BytesType.class.getSimpleName(),
+                ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
+                MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
+
+        return Arrays.asList( uniqueLookupCF, uniqueLogCF );
+    }
+
+
+    @Override
+    protected MultiTennantColumnFamily<ScopedRowKey<CollectionPrefixedKey<Field>>, EntityVersion> getUniqueValuesCF() {
+        return CF_UNIQUE_VALUES;
+    }
+
+
+    @Override
+    protected MultiTennantColumnFamily<ScopedRowKey<CollectionPrefixedKey<Id>>, UniqueFieldEntry>
+    getEntityUniqueLogCF() {
+        return CF_ENTITY_UNIQUE_VALUE_LOG;
+    }
+
+
+    @Override
+    protected CollectionPrefixedKey<Field> createUniqueValueKey( final Id applicationId,
+                                                                 final String type, final Field field) {
+
+
+        final String collectionName = LegacyScopeUtils.getCollectionScopeNameFromEntityType( type );
+
+
+        final CollectionPrefixedKey<Field> uniquePrefixedKey =
+            new CollectionPrefixedKey<>( collectionName, applicationId, field );
+
+        return uniquePrefixedKey;
+    }
+
+
+    @Override
+    protected Field parseRowKey( final ScopedRowKey<CollectionPrefixedKey<Field>> rowKey ) {
+        return rowKey.getKey().getSubKey();
+    }
+
+
+    @Override
+    protected CollectionPrefixedKey<Id> createEntityUniqueLogKey( final Id applicationId,
+                                                                  final Id uniqueValueId ) {
+
+
+        final String collectionName = LegacyScopeUtils.getCollectionScopeNameFromEntityType( uniqueValueId.getType() );
+
+
+        final CollectionPrefixedKey<Id> collectionPrefixedEntityKey =
+            new CollectionPrefixedKey<>( collectionName, applicationId, uniqueValueId );
+
+
+
+        return collectionPrefixedEntityKey;
+    }
+
+
+    @Override
+    public int getImplementationVersion() {
+        return CollectionDataVersions.INITIAL.getVersion();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2Impl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2Impl.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2Impl.java
new file mode 100644
index 0000000..baeec22
--- /dev/null
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyV2Impl.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.usergrid.persistence.collection.serialization.impl;
+
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.cassandra.db.marshal.BytesType;
+
+import org.apache.usergrid.persistence.collection.serialization.SerializationFig;
+import org.apache.usergrid.persistence.collection.serialization.impl.util.LegacyScopeUtils;
+import org.apache.usergrid.persistence.core.astyanax.CassandraFig;
+import org.apache.usergrid.persistence.core.astyanax.ColumnTypes;
+import org.apache.usergrid.persistence.core.astyanax.IdRowCompositeSerializer;
+import org.apache.usergrid.persistence.core.astyanax.MultiTennantColumnFamily;
+import org.apache.usergrid.persistence.core.astyanax.MultiTennantColumnFamilyDefinition;
+import org.apache.usergrid.persistence.core.astyanax.ScopedRowKey;
+import org.apache.usergrid.persistence.core.astyanax.ScopedRowKeySerializer;
+import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.field.Field;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.netflix.astyanax.Keyspace;
+
+
+/**
+ * V1 impl with unique value serialization strategy with the collection scope
+ */
+@Singleton
+public class UniqueValueSerializationStrategyV2Impl  extends UniqueValueSerializationStrategyImpl<Field, Id> {
+
+
+    private static final ScopedRowKeySerializer<Field>  ROW_KEY_SER = new ScopedRowKeySerializer<>( UniqueFieldRowKeySerializer.get() );
+
+
+    private static final EntityVersionSerializer ENTITY_VERSION_SER = new EntityVersionSerializer();
+
+    private static final MultiTennantColumnFamily<ScopedRowKey<Field>, EntityVersion>
+        CF_UNIQUE_VALUES = new MultiTennantColumnFamily<>( "Unique_Values_V2", ROW_KEY_SER, ENTITY_VERSION_SER );
+
+
+    private static final IdRowCompositeSerializer ID_SER = IdRowCompositeSerializer.get();
+
+
+    private static final ScopedRowKeySerializer<Id> ENTITY_ROW_KEY_SER =
+        new ScopedRowKeySerializer<>( ID_SER );
+
+
+    private static final MultiTennantColumnFamily<ScopedRowKey<Id>, UniqueFieldEntry>
+        CF_ENTITY_UNIQUE_VALUE_LOG =
+        new MultiTennantColumnFamily<>( "Entity_Unique_Values_V2", ENTITY_ROW_KEY_SER, UniqueFieldEntrySerializer.get() );
+
+
+    /**
+     * Construct serialization strategy for keyspace.
+     *
+     * @param keyspace Keyspace in which to store Unique Values.
+     * @param cassandraFig The cassandra configuration
+     * @param serializationFig The serialization configuration
+     */
+    @Inject
+    public UniqueValueSerializationStrategyV2Impl( final Keyspace keyspace, final CassandraFig cassandraFig,
+                                                   final SerializationFig serializationFig ) {
+        super( keyspace, cassandraFig, serializationFig );
+    }
+
+
+    @Override
+    public Collection<MultiTennantColumnFamilyDefinition> getColumnFamilies() {
+
+        final MultiTennantColumnFamilyDefinition uniqueLookupCF =
+            new MultiTennantColumnFamilyDefinition( CF_UNIQUE_VALUES, BytesType.class.getSimpleName(),
+                ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
+                MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
+
+        final MultiTennantColumnFamilyDefinition uniqueLogCF =
+            new MultiTennantColumnFamilyDefinition( CF_ENTITY_UNIQUE_VALUE_LOG, BytesType.class.getSimpleName(),
+                ColumnTypes.DYNAMIC_COMPOSITE_TYPE, BytesType.class.getSimpleName(),
+                MultiTennantColumnFamilyDefinition.CacheOption.KEYS );
+
+        return Arrays.asList( uniqueLookupCF, uniqueLogCF );
+    }
+
+
+    @Override
+    protected MultiTennantColumnFamily<ScopedRowKey<Field>, EntityVersion> getUniqueValuesCF() {
+        return CF_UNIQUE_VALUES;
+    }
+
+
+    @Override
+    protected MultiTennantColumnFamily<ScopedRowKey<Id>, UniqueFieldEntry>
+    getEntityUniqueLogCF() {
+        return CF_ENTITY_UNIQUE_VALUE_LOG;
+    }
+
+
+    @Override
+    protected Field createUniqueValueKey( final Id applicationId,  final String type, final Field field) {
+        return field;
+    }
+
+
+    @Override
+    protected Field parseRowKey( final ScopedRowKey<Field> rowKey ) {
+        return rowKey.getKey();
+    }
+
+
+    @Override
+    protected Id createEntityUniqueLogKey( final Id applicationId, final Id uniqueValueId ) {
+       return uniqueValueId;
+    }
+
+
+    @Override
+    public int getImplementationVersion() {
+        return CollectionDataVersions.LOG_REMOVAL.getVersion();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/UniqueValueSerializationStrategyImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/UniqueValueSerializationStrategyImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/UniqueValueSerializationStrategyImplTest.java
deleted file mode 100644
index e1647b3..0000000
--- a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/UniqueValueSerializationStrategyImplTest.java
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  The ASF licenses this file to You
- * 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.  For additional information regarding
- * copyright in this work, please see the NOTICE file in the top level
- * directory of this distribution.
- */
-package org.apache.usergrid.persistence.collection.mvcc.stage.write;
-
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.UUID;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
-import org.apache.usergrid.persistence.collection.serialization.UniqueValue;
-import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
-import org.apache.usergrid.persistence.collection.serialization.UniqueValueSet;
-import org.apache.usergrid.persistence.collection.serialization.impl.UniqueValueImpl;
-import org.apache.usergrid.persistence.core.guice.MigrationManagerRule;
-import org.apache.usergrid.persistence.core.scope.ApplicationScope;
-import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl;
-import org.apache.usergrid.persistence.core.test.ITRunner;
-import org.apache.usergrid.persistence.core.test.UseModules;
-import org.apache.usergrid.persistence.model.entity.Id;
-import org.apache.usergrid.persistence.model.entity.SimpleId;
-import org.apache.usergrid.persistence.model.field.Field;
-import org.apache.usergrid.persistence.model.field.IntegerField;
-import org.apache.usergrid.persistence.model.field.StringField;
-import org.apache.usergrid.persistence.model.util.UUIDGenerator;
-
-import com.google.inject.Inject;
-import com.netflix.astyanax.MutationBatch;
-import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-
-@RunWith(ITRunner.class)
-@UseModules(TestCollectionModule.class)
-public class UniqueValueSerializationStrategyImplTest {
-
-
-    @Inject
-    @Rule
-    public MigrationManagerRule migrationManagerRule;
-
-    @Inject
-    UniqueValueSerializationStrategy strategy;
-
-
-    @Test
-    public void testBasicOperation() throws ConnectionException, InterruptedException {
-
-        ApplicationScope scope =
-                new ApplicationScopeImpl( new SimpleId( "organization" ) );
-
-        IntegerField field = new IntegerField( "count", 5 );
-        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
-        UUID version = UUIDGenerator.newTimeUUID();
-        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
-        strategy.write( scope, stored ).execute();
-
-        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
-
-        UniqueValue retrieved = fields.getValue( field.getName() );
-        Assert.assertNotNull( retrieved );
-        assertEquals( stored, retrieved );
-
-        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
-
-        assertTrue(allFieldsWritten.hasNext());
-
-        //test this interface. In most cases, we won't know the field name, so we want them all
-        UniqueValue allFieldsValue = allFieldsWritten.next();
-        Assert.assertNotNull( allFieldsValue );
-
-        assertEquals( field, allFieldsValue.getField() );
-        assertEquals(version, allFieldsValue.getEntityVersion());
-
-        assertFalse(allFieldsWritten.hasNext());
-
-    }
-
-
-    @Test
-    public void testWriteWithTTL() throws InterruptedException, ConnectionException {
-
-
-        ApplicationScope scope =
-                new ApplicationScopeImpl( new SimpleId( "organization" ) );
-
-        // write object that lives 2 seconds
-        IntegerField field = new IntegerField( "count", 5 );
-        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
-        UUID version = UUIDGenerator.newTimeUUID();
-        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
-        strategy.write( scope, stored, 2 ).execute();
-
-        Thread.sleep( 1000 );
-
-        // waited one sec, should be still here
-        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
-
-        UniqueValue retrieved = fields.getValue( field.getName() );
-
-        Assert.assertNotNull( retrieved );
-        assertEquals( stored, retrieved );
-
-        Thread.sleep( 1500 );
-
-        // wait another second, should be gone now
-        fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
-
-        UniqueValue nullExpected = fields.getValue( field.getName() );
-        Assert.assertNull( nullExpected );
-
-
-        //we still want to retain the log entry, even if we don't retain the unique value.  Deleting something
-        //that doesn't exist is a tombstone, but so is the timeout.
-        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
-
-        assertTrue( allFieldsWritten.hasNext() );
-
-        //test this interface. In most cases, we won't know the field name, so we want them all
-        UniqueValue writtenFieldEntry = allFieldsWritten.next();
-        Assert.assertNotNull( writtenFieldEntry );
-
-        assertEquals( field, writtenFieldEntry.getField() );
-        assertEquals( version, writtenFieldEntry.getEntityVersion() );
-
-        assertFalse(allFieldsWritten.hasNext());
-
-
-
-    }
-
-
-    @Test
-    public void testDelete() throws ConnectionException {
-
-
-        ApplicationScope scope =
-                new ApplicationScopeImpl( new SimpleId( "organization" ) );
-
-        IntegerField field = new IntegerField( "count", 5 );
-        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
-        UUID version = UUIDGenerator.newTimeUUID();
-        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
-        strategy.write( scope, stored ).execute();
-
-        strategy.delete( scope, stored ).execute();
-
-        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
-
-        UniqueValue nullExpected = fields.getValue( field.getName() );
-
-
-        Assert.assertNull( nullExpected );
-
-
-        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
-
-        assertFalse("No entries left",  allFieldsWritten.hasNext() );
-    }
-
-
-    @Test
-    public void testCapitalizationFixes() throws ConnectionException {
-
-        ApplicationScope scope =
-                new ApplicationScopeImpl( new SimpleId( "organization" ) );
-
-        StringField field = new StringField( "count", "MiXeD CaSe" );
-        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
-        UUID version = UUIDGenerator.newTimeUUID();
-        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
-        strategy.write( scope, stored ).execute();
-
-
-        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
-
-        UniqueValue value = fields.getValue( field.getName() );
-
-
-        assertEquals( field.getName(), value.getField().getName() );
-
-        assertEquals( entityId, value.getEntityId() );
-
-        //now test will all upper and all lower, we should get it all the same
-        fields = strategy.load( scope, entityId.getType(),
-                Collections.<Field>singleton( new StringField( field.getName(), "MIXED CASE" ) ) );
-
-        value = fields.getValue( field.getName() );
-
-
-        assertEquals( field.getName(), value.getField().getName() );
-
-        assertEquals( entityId, value.getEntityId() );
-
-        fields = strategy.load( scope, entityId.getType(),
-                Collections.<Field>singleton( new StringField( field.getName(), "mixed case" ) ) );
-
-        value = fields.getValue( field.getName() );
-
-
-        assertEquals( field.getName(), value.getField().getName() );
-
-        assertEquals( entityId, value.getEntityId() );
-
-
-        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
-
-        assertTrue( allFieldsWritten.hasNext() );
-
-        //test this interface. In most cases, we won't know the field name, so we want them all
-        UniqueValue writtenFieldEntry = allFieldsWritten.next();
-        Assert.assertNotNull( writtenFieldEntry );
-
-        assertEquals( field.getName(), writtenFieldEntry.getField().getName() );
-        assertEquals( field.getValue().toLowerCase(), writtenFieldEntry.getField().getValue() );
-        assertEquals( version, writtenFieldEntry.getEntityVersion() );
-
-        assertFalse(allFieldsWritten.hasNext());
-    }
-
-
-
-    @Test
-    public void twoFieldsPerVersion() throws ConnectionException, InterruptedException {
-
-
-        ApplicationScope scope =
-                new ApplicationScopeImpl( new SimpleId( "organization" ) );
-
-
-        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
-        final UUID version1 = UUIDGenerator.newTimeUUID();
-
-
-        //write V1 of everything
-        IntegerField version1Field1 = new IntegerField( "count", 1 );
-        StringField version1Field2 = new StringField("field", "v1value");
-
-
-        UniqueValue version1Field1Value = new UniqueValueImpl( version1Field1, entityId, version1 );
-        UniqueValue version1Field2Value = new UniqueValueImpl( version1Field2, entityId, version1 );
-
-        final MutationBatch batch = strategy.write( scope, version1Field1Value );
-        batch.mergeShallow( strategy.write( scope, version1Field2Value ) );
-
-
-        //write V2 of everything
-        final UUID version2 = UUIDGenerator.newTimeUUID();
-
-        IntegerField version2Field1 = new IntegerField( "count", 2 );
-        StringField version2Field2 = new StringField( "field", "v2value" );
-
-
-        UniqueValue version2Field1Value = new UniqueValueImpl( version2Field1, entityId, version2 );
-        UniqueValue version2Field2Value = new UniqueValueImpl( version2Field2, entityId, version2 );
-
-        batch.mergeShallow( strategy.write( scope, version2Field1Value ) );
-        batch.mergeShallow( strategy.write( scope, version2Field2Value ) );
-
-        batch.execute();
-
-
-        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Arrays.<Field>asList( version1Field1, version1Field2 ) );
-
-        UniqueValue retrieved = fields.getValue( version1Field1.getName() );
-
-        assertEquals( version1Field1Value, retrieved );
-
-
-        retrieved = fields.getValue( version1Field2.getName() );
-        assertEquals( version1Field2Value, retrieved );
-
-
-        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
-
-        assertTrue(allFieldsWritten.hasNext());
-
-        //test this interface. In most cases, we won't know the field name, so we want them all
-        UniqueValue allFieldsValue = allFieldsWritten.next();
-
-        //version 2 fields should come first, ordered by field name
-        assertEquals( version2Field1, allFieldsValue.getField() );
-        assertEquals( version2, allFieldsValue.getEntityVersion() );
-
-        allFieldsValue = allFieldsWritten.next();
-
-        assertEquals( version2Field2, allFieldsValue.getField() );
-        assertEquals( version2, allFieldsValue.getEntityVersion() );
-
-
-        //version 1 should come next ordered by field name
-        allFieldsValue = allFieldsWritten.next();
-
-        assertEquals( version1Field1, allFieldsValue.getField() );
-        assertEquals( version1, allFieldsValue.getEntityVersion() );
-
-        allFieldsValue = allFieldsWritten.next();
-
-        assertEquals( version1Field2, allFieldsValue.getField() );
-        assertEquals( version1, allFieldsValue.getEntityVersion() );
-
-        assertFalse(allFieldsWritten.hasNext());
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java
new file mode 100644
index 0000000..2fae482
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyImplTest.java
@@ -0,0 +1,344 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * 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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.usergrid.persistence.collection.serialization.impl;
+
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValue;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValueSet;
+import org.apache.usergrid.persistence.collection.serialization.impl.UniqueValueImpl;
+import org.apache.usergrid.persistence.core.guice.MigrationManagerRule;
+import org.apache.usergrid.persistence.core.scope.ApplicationScope;
+import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl;
+import org.apache.usergrid.persistence.core.test.ITRunner;
+import org.apache.usergrid.persistence.core.test.UseModules;
+import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.entity.SimpleId;
+import org.apache.usergrid.persistence.model.field.Field;
+import org.apache.usergrid.persistence.model.field.IntegerField;
+import org.apache.usergrid.persistence.model.field.StringField;
+import org.apache.usergrid.persistence.model.util.UUIDGenerator;
+
+import com.google.inject.Inject;
+import com.netflix.astyanax.MutationBatch;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+
+@RunWith(ITRunner.class)
+@UseModules(TestCollectionModule.class)
+public abstract class UniqueValueSerializationStrategyImplTest {
+
+
+    @Inject
+    @Rule
+    public MigrationManagerRule migrationManagerRule;
+
+
+    private UniqueValueSerializationStrategy strategy;
+
+
+    @Before
+    public void wireUniqueSerializationStrategy(){
+        strategy = getUniqueSerializationStrategy();
+    }
+
+
+    /**
+     * Get the unique value serialization
+     * @return
+     */
+    protected abstract UniqueValueSerializationStrategy getUniqueSerializationStrategy();
+
+
+    @Test
+    public void testBasicOperation() throws ConnectionException, InterruptedException {
+
+        ApplicationScope scope =
+                new ApplicationScopeImpl( new SimpleId( "organization" ) );
+
+        IntegerField field = new IntegerField( "count", 5 );
+        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+        UUID version = UUIDGenerator.newTimeUUID();
+        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
+        strategy.write( scope, stored ).execute();
+
+        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
+
+        UniqueValue retrieved = fields.getValue( field.getName() );
+        Assert.assertNotNull( retrieved );
+        assertEquals( stored, retrieved );
+
+        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
+
+        assertTrue(allFieldsWritten.hasNext());
+
+        //test this interface. In most cases, we won't know the field name, so we want them all
+        UniqueValue allFieldsValue = allFieldsWritten.next();
+        Assert.assertNotNull( allFieldsValue );
+
+        assertEquals( field, allFieldsValue.getField() );
+        assertEquals(version, allFieldsValue.getEntityVersion());
+
+        assertFalse(allFieldsWritten.hasNext());
+
+    }
+
+
+    @Test
+    public void testWriteWithTTL() throws InterruptedException, ConnectionException {
+
+
+        ApplicationScope scope =
+                new ApplicationScopeImpl( new SimpleId( "organization" ) );
+
+        // write object that lives 2 seconds
+        IntegerField field = new IntegerField( "count", 5 );
+        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+        UUID version = UUIDGenerator.newTimeUUID();
+        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
+        strategy.write( scope, stored, 2 ).execute();
+
+        Thread.sleep( 1000 );
+
+        // waited one sec, should be still here
+        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
+
+        UniqueValue retrieved = fields.getValue( field.getName() );
+
+        Assert.assertNotNull( retrieved );
+        assertEquals( stored, retrieved );
+
+        Thread.sleep( 1500 );
+
+        // wait another second, should be gone now
+        fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
+
+        UniqueValue nullExpected = fields.getValue( field.getName() );
+        Assert.assertNull( nullExpected );
+
+
+        //we still want to retain the log entry, even if we don't retain the unique value.  Deleting something
+        //that doesn't exist is a tombstone, but so is the timeout.
+        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
+
+        assertTrue( allFieldsWritten.hasNext() );
+
+        //test this interface. In most cases, we won't know the field name, so we want them all
+        UniqueValue writtenFieldEntry = allFieldsWritten.next();
+        Assert.assertNotNull( writtenFieldEntry );
+
+        assertEquals( field, writtenFieldEntry.getField() );
+        assertEquals( version, writtenFieldEntry.getEntityVersion() );
+
+        assertFalse(allFieldsWritten.hasNext());
+
+
+
+    }
+
+
+    @Test
+    public void testDelete() throws ConnectionException {
+
+
+        ApplicationScope scope =
+                new ApplicationScopeImpl( new SimpleId( "organization" ) );
+
+        IntegerField field = new IntegerField( "count", 5 );
+        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+        UUID version = UUIDGenerator.newTimeUUID();
+        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
+        strategy.write( scope, stored ).execute();
+
+        strategy.delete( scope, stored ).execute();
+
+        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
+
+        UniqueValue nullExpected = fields.getValue( field.getName() );
+
+
+        Assert.assertNull( nullExpected );
+
+
+        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
+
+        assertFalse("No entries left",  allFieldsWritten.hasNext() );
+    }
+
+
+    @Test
+    public void testCapitalizationFixes() throws ConnectionException {
+
+        ApplicationScope scope =
+                new ApplicationScopeImpl( new SimpleId( "organization" ) );
+
+        StringField field = new StringField( "count", "MiXeD CaSe" );
+        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+        UUID version = UUIDGenerator.newTimeUUID();
+        UniqueValue stored = new UniqueValueImpl( field, entityId, version );
+        strategy.write( scope, stored ).execute();
+
+
+        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Collections.<Field>singleton( field ) );
+
+        UniqueValue value = fields.getValue( field.getName() );
+
+
+        assertEquals( field.getName(), value.getField().getName() );
+
+        assertEquals( entityId, value.getEntityId() );
+
+        //now test will all upper and all lower, we should get it all the same
+        fields = strategy.load( scope, entityId.getType(),
+                Collections.<Field>singleton( new StringField( field.getName(), "MIXED CASE" ) ) );
+
+        value = fields.getValue( field.getName() );
+
+
+        assertEquals( field.getName(), value.getField().getName() );
+
+        assertEquals( entityId, value.getEntityId() );
+
+        fields = strategy.load( scope, entityId.getType(),
+                Collections.<Field>singleton( new StringField( field.getName(), "mixed case" ) ) );
+
+        value = fields.getValue( field.getName() );
+
+
+        assertEquals( field.getName(), value.getField().getName() );
+
+        assertEquals( entityId, value.getEntityId() );
+
+
+        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
+
+        assertTrue( allFieldsWritten.hasNext() );
+
+        //test this interface. In most cases, we won't know the field name, so we want them all
+        UniqueValue writtenFieldEntry = allFieldsWritten.next();
+        Assert.assertNotNull( writtenFieldEntry );
+
+        assertEquals( field.getName(), writtenFieldEntry.getField().getName() );
+        assertEquals( field.getValue().toLowerCase(), writtenFieldEntry.getField().getValue() );
+        assertEquals( version, writtenFieldEntry.getEntityVersion() );
+
+        assertFalse(allFieldsWritten.hasNext());
+    }
+
+
+
+    @Test
+    public void twoFieldsPerVersion() throws ConnectionException, InterruptedException {
+
+
+        ApplicationScope scope =
+                new ApplicationScopeImpl( new SimpleId( "organization" ) );
+
+
+        Id entityId = new SimpleId( UUIDGenerator.newTimeUUID(), "entity" );
+        final UUID version1 = UUIDGenerator.newTimeUUID();
+
+
+        //write V1 of everything
+        IntegerField version1Field1 = new IntegerField( "count", 1 );
+        StringField version1Field2 = new StringField("field", "v1value");
+
+
+        UniqueValue version1Field1Value = new UniqueValueImpl( version1Field1, entityId, version1 );
+        UniqueValue version1Field2Value = new UniqueValueImpl( version1Field2, entityId, version1 );
+
+        final MutationBatch batch = strategy.write( scope, version1Field1Value );
+        batch.mergeShallow( strategy.write( scope, version1Field2Value ) );
+
+
+        //write V2 of everything
+        final UUID version2 = UUIDGenerator.newTimeUUID();
+
+        IntegerField version2Field1 = new IntegerField( "count", 2 );
+        StringField version2Field2 = new StringField( "field", "v2value" );
+
+
+        UniqueValue version2Field1Value = new UniqueValueImpl( version2Field1, entityId, version2 );
+        UniqueValue version2Field2Value = new UniqueValueImpl( version2Field2, entityId, version2 );
+
+        batch.mergeShallow( strategy.write( scope, version2Field1Value ) );
+        batch.mergeShallow( strategy.write( scope, version2Field2Value ) );
+
+        batch.execute();
+
+
+        UniqueValueSet fields = strategy.load( scope, entityId.getType(), Arrays.<Field>asList( version1Field1, version1Field2 ) );
+
+        UniqueValue retrieved = fields.getValue( version1Field1.getName() );
+
+        assertEquals( version1Field1Value, retrieved );
+
+
+        retrieved = fields.getValue( version1Field2.getName() );
+        assertEquals( version1Field2Value, retrieved );
+
+
+        Iterator<UniqueValue> allFieldsWritten = strategy.getAllUniqueFields( scope, entityId );
+
+        assertTrue(allFieldsWritten.hasNext());
+
+        //test this interface. In most cases, we won't know the field name, so we want them all
+        UniqueValue allFieldsValue = allFieldsWritten.next();
+
+        //version 2 fields should come first, ordered by field name
+        assertEquals( version2Field1, allFieldsValue.getField() );
+        assertEquals( version2, allFieldsValue.getEntityVersion() );
+
+        allFieldsValue = allFieldsWritten.next();
+
+        assertEquals( version2Field2, allFieldsValue.getField() );
+        assertEquals( version2, allFieldsValue.getEntityVersion() );
+
+
+        //version 1 should come next ordered by field name
+        allFieldsValue = allFieldsWritten.next();
+
+        assertEquals( version1Field1, allFieldsValue.getField() );
+        assertEquals( version1, allFieldsValue.getEntityVersion() );
+
+        allFieldsValue = allFieldsWritten.next();
+
+        assertEquals( version1Field2, allFieldsValue.getField() );
+        assertEquals( version1, allFieldsValue.getEntityVersion() );
+
+        assertFalse(allFieldsWritten.hasNext());
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/d145eb4b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImplTest.java
new file mode 100644
index 0000000..a74ddc2
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/serialization/impl/UniqueValueSerializationStrategyProxyImplTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.usergrid.persistence.collection.serialization.impl;
+
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
+import org.apache.usergrid.persistence.collection.serialization.MvccLogEntrySerializationStrategy;
+import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
+import org.apache.usergrid.persistence.collection.serialization.impl.migration.CollectionMigrationPlugin;
+import org.apache.usergrid.persistence.core.migration.data.MigrationInfoSerialization;
+import org.apache.usergrid.persistence.core.test.ITRunner;
+import org.apache.usergrid.persistence.core.test.UseModules;
+
+import com.google.inject.Inject;
+import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+
+import net.jcip.annotations.NotThreadSafe;
+
+import static org.junit.Assert.assertEquals;
+
+
+@RunWith( ITRunner.class )
+@UseModules( TestCollectionModule.class )
+@NotThreadSafe
+public class UniqueValueSerializationStrategyProxyImplTest extends UniqueValueSerializationStrategyImplTest {
+
+    @Inject
+    private UniqueValueSerializationStrategyV1Impl strategy;
+
+
+    @Inject
+    private UniqueValueSerializationStrategyV1Impl v1Impl;
+
+
+
+    /**
+     * Get the unique value serialization
+     */
+    protected UniqueValueSerializationStrategy getUniqueSerializationStrategy() {
+        return strategy;
+    }
+
+
+
+
+
+
+    @Inject
+    protected MigrationInfoSerialization migrationInfoSerialization;
+
+    private int existingVersion;
+
+
+
+
+
+
+    /**
+     * We need to run our migration to ensure that we are on the current version, and everything still functions
+     * correctly
+     */
+    @Before
+    public void setMigrationVersion() {
+        existingVersion = migrationInfoSerialization.getVersion( CollectionMigrationPlugin.PLUGIN_NAME);
+
+        //set our migration version to be v1
+        migrationInfoSerialization.setVersion( CollectionMigrationPlugin.PLUGIN_NAME, v1Impl.getImplementationVersion() );
+    }
+
+
+
+
+    @After
+    public void reSetMigrationVersion() {
+        migrationInfoSerialization.setVersion( CollectionMigrationPlugin.PLUGIN_NAME, existingVersion );
+    }
+
+}