You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2014/03/12 19:20:59 UTC
[3/4] git commit: We now cleanup and unique values on version
conflict; also, added better tests for optimistic and unique verification.
We now cleanup and unique values on version conflict; also, added better tests for optimistic and unique verification.
Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/29a4966b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/29a4966b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/29a4966b
Branch: refs/pull/52/merge
Commit: 29a4966b4b4682f42e22dacfc9f55c69a5f61b78
Parents: e072f0b
Author: Dave Johnson <dm...@apigee.com>
Authored: Wed Mar 12 14:11:32 2014 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Wed Mar 12 14:11:32 2014 -0400
----------------------------------------------------------------------
.../exception/WriteUniqueVerifyException.java | 24 ++-
.../mvcc/stage/write/WriteOptimisticVerify.java | 114 +++++++++++-
.../mvcc/stage/write/WriteUniqueVerify.java | 69 ++++----
.../mvcc/entity/impl/MvccEntityImplTest.java | 23 ++-
.../stage/write/WriteOptimisticVerifyTest.java | 78 ++++++--
.../mvcc/stage/write/WriteUniqueVerifyIT.java | 97 ++++++++++
.../mvcc/stage/write/WriteUniqueVerifyTest.java | 23 ---
.../collection/util/EntityBuilder.java | 177 +++++++++++++++++++
.../src/test/resources/log4j.properties | 4 +-
.../index/impl/EntityCollectionIndexTest.java | 2 +-
.../persistence/index/legacy/EntityBuilder.java | 177 -------------------
.../index/legacy/EntityManagerFacade.java | 1 +
12 files changed, 525 insertions(+), 264 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/exception/WriteUniqueVerifyException.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/exception/WriteUniqueVerifyException.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/exception/WriteUniqueVerifyException.java
index a003b16..66b3076 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/exception/WriteUniqueVerifyException.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/exception/WriteUniqueVerifyException.java
@@ -17,13 +17,20 @@
*/
package org.apache.usergrid.persistence.collection.exception;
-public class WriteUniqueVerifyException extends CollectionRuntimeException {
- public WriteUniqueVerifyException() {
- }
+import java.util.Map;
+import org.apache.usergrid.persistence.model.field.Field;
- public WriteUniqueVerifyException( final String message ) {
- super( message );
+/**
+ * Indicates that one or more unique field checks failed.
+ */
+public class WriteUniqueVerifyException extends CollectionRuntimeException {
+ private Map<String, Field> violations;
+
+
+ public WriteUniqueVerifyException( Map<String, Field> violations ) {
+ super( "Error: one or more duplicate fields detected");
+ this.violations = violations;
}
@@ -41,4 +48,11 @@ public class WriteUniqueVerifyException extends CollectionRuntimeException {
final boolean writableStackTrace ) {
super( message, cause, enableSuppression, writableStackTrace );
}
+
+ /**
+ * Get map of Fields in violation, keyed by field name.
+ */
+ public Map<String, Field> getVioliations() {
+ return violations;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerify.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerify.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerify.java
index 3196404..061595c 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerify.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerify.java
@@ -20,10 +20,14 @@ package org.apache.usergrid.persistence.collection.mvcc.stage.write;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import com.netflix.astyanax.MutationBatch;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+import java.util.ArrayList;
import java.util.List;
import org.apache.usergrid.persistence.collection.CollectionScope;
+import org.apache.usergrid.persistence.collection.exception.CollectionRuntimeException;
import org.apache.usergrid.persistence.collection.exception.WriteOptimisticVerifyException;
+import org.apache.usergrid.persistence.collection.exception.WriteUniqueVerifyException;
import org.apache.usergrid.persistence.collection.mvcc.MvccLogEntrySerializationStrategy;
import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntity;
import org.apache.usergrid.persistence.collection.mvcc.entity.MvccLogEntry;
@@ -31,9 +35,14 @@ import org.apache.usergrid.persistence.collection.mvcc.entity.Stage;
import org.apache.usergrid.persistence.collection.mvcc.entity.ValidationUtils;
import org.apache.usergrid.persistence.collection.mvcc.entity.impl.MvccLogEntryImpl;
import org.apache.usergrid.persistence.collection.mvcc.stage.CollectionIoEvent;
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.apache.usergrid.persistence.model.field.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import rx.Observable;
+import rx.Scheduler;
import rx.util.functions.Func1;
+import rx.util.functions.FuncN;
/**
@@ -43,13 +52,21 @@ import rx.util.functions.Func1;
public class WriteOptimisticVerify
implements Func1<CollectionIoEvent<MvccEntity>, CollectionIoEvent<MvccEntity>> {
- private static final Logger LOG = LoggerFactory.getLogger( WriteOptimisticVerify.class );
+ private static final Logger log = LoggerFactory.getLogger( WriteOptimisticVerify.class );
private final MvccLogEntrySerializationStrategy logEntryStrat;
+ private final UniqueValueSerializationStrategy uniqueValueStrat;
+
+ private final Scheduler scheduler;
+
@Inject
- public WriteOptimisticVerify( MvccLogEntrySerializationStrategy logEntryStrat ) {
+ public WriteOptimisticVerify( MvccLogEntrySerializationStrategy logEntryStrat,
+ final UniqueValueSerializationStrategy uniqueValueStrat, final Scheduler scheduler ) {
+
this.logEntryStrat = logEntryStrat;
+ this.uniqueValueStrat = uniqueValueStrat;
+ this.scheduler = scheduler;
}
@@ -63,7 +80,9 @@ public class WriteOptimisticVerify
//
// If not, fail fast, signal to the user their entity is "stale".
- MvccEntity entity = ioevent.getEvent();
+ MvccEntity mvccEntity = ioevent.getEvent();
+ final Entity entity = mvccEntity.getEntity().get();
+
CollectionScope collectionScope = ioevent.getEntityCollection();
try {
@@ -73,21 +92,102 @@ public class WriteOptimisticVerify
// Previous log entry must be committed, otherwise somebody is already writing
if ( versions.size() > 1
&& versions.get(1).getStage().ordinal() < Stage.COMMITTED.ordinal() ) {
+
+ log.debug("Conflict writing entity id {} version {}",
+ entity.getId().toString(), entity.getVersion().toString());
- // We're not the first writer, rollback and throw-up
+ // We're not the first writer, set ROLLBACK, cleanup and throw exception
+
final MvccLogEntry rollbackEntry =
- new MvccLogEntryImpl( entity.getId(), entity.getVersion(), Stage.ROLLBACK);
+ new MvccLogEntryImpl( entity.getId(), entity.getVersion(), Stage.ROLLBACK);
logEntryStrat.write( collectionScope, rollbackEntry );
+
+ // Delete all unique values of entity, and do it concurrently
+
+ List<Observable<FieldDeleteResult>> results =
+ new ArrayList<Observable<FieldDeleteResult>>();
+
+ int uniqueFieldCount = 0;
+ for ( final Field field : entity.getFields() ) {
+
+ // if it's unique, create a function to delete it
+ if ( field.isUnique() ) {
+
+ uniqueFieldCount++;
+
+ Observable<FieldDeleteResult> result = Observable.from( field )
+ .subscribeOn( scheduler ).map(new Func1<Field, FieldDeleteResult>() {
+
+ @Override
+ public FieldDeleteResult call(Field field ) {
+
+ UniqueValue toDelete = new UniqueValueImpl(
+ ioevent.getEntityCollection(), field,
+ entity.getId(), entity.getVersion() );
+
+ MutationBatch mb = uniqueValueStrat.delete( toDelete );
+ try {
+ mb.execute();
+ }
+ catch ( ConnectionException ex ) {
+ throw new WriteUniqueVerifyException(
+ "Error deleting unique value " + field.toString(), ex );
+ }
+ return new FieldDeleteResult( field.getName() );
+ }
+ });
+
+ results.add( result );
+ }
+ }
+
+ if ( uniqueFieldCount > 0 ) {
+
+ final FuncN<Boolean> zipFunction = new FuncN<Boolean>() {
+
+ @Override
+ public Boolean call( final Object... args ) {
+ for ( Object resultObj : args ) {
+
+ FieldDeleteResult result = ( FieldDeleteResult ) resultObj;
+ log.debug("Rollback deleted field from entity: {} version: {} name: {}",
+ new String[] {
+ entity.getId().toString(),
+ entity.getVersion().toString(),
+ result.getName()
+ });
+ }
+ return true;
+ }
+ };
+
+ // "zip" up the concurrent results
+ Observable.zip( results, zipFunction ).toBlockingObservable().last();
+ }
+
throw new WriteOptimisticVerifyException("Change conflict, not first writer");
}
} catch ( ConnectionException e ) {
- LOG.error( "Error reading entity log", e );
- throw new WriteOptimisticVerifyException( "Error reading entity log", e );
+ log.error( "Error reading entity log", e );
+ throw new CollectionRuntimeException( "Error reading entity log", e );
}
// No op, just emit the value
return ioevent;
}
+
+
+ class FieldDeleteResult {
+ private final String name;
+
+ public FieldDeleteResult( String name ) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
index 02ed9db..ca99c0c 100644
--- a/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
+++ b/stack/corepersistence/collection/src/main/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerify.java
@@ -36,6 +36,8 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.netflix.astyanax.MutationBatch;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.usergrid.persistence.collection.exception.WriteUniqueVerifyException;
import rx.Observable;
@@ -48,34 +50,35 @@ import rx.util.functions.FuncN;
* This phase execute all unique value verification on the MvccEntity.
*/
@Singleton
-public class WriteUniqueVerify implements Func1<CollectionIoEvent<MvccEntity>, Observable<? extends CollectionIoEvent<MvccEntity>>> {
+public class WriteUniqueVerify implements
+ Func1<CollectionIoEvent<MvccEntity>, Observable<? extends CollectionIoEvent<MvccEntity>>> {
private static final Logger LOG = LoggerFactory.getLogger( WriteUniqueVerify.class );
private final UniqueValueSerializationStrategy uniqueValueStrat;
-
private final Scheduler scheduler;
protected final SerializationFig serializationFig;
@Inject
- public WriteUniqueVerify( final UniqueValueSerializationStrategy uniqueValueSerializiationStrategy,
+ public WriteUniqueVerify( final UniqueValueSerializationStrategy uniqueValueStrat,
final Scheduler scheduler, final SerializationFig serializationFig ) {
- Preconditions.checkNotNull( uniqueValueSerializiationStrategy, "uniqueValueSerializationStrategy is required" );
+ Preconditions.checkNotNull( uniqueValueStrat, "uniqueValueStrat is required" );
Preconditions.checkNotNull( scheduler, "scheduler is required" );
Preconditions.checkNotNull( serializationFig, "serializationFig is required" );
- this.uniqueValueStrat = uniqueValueSerializiationStrategy;
+ this.uniqueValueStrat = uniqueValueStrat;
this.scheduler = scheduler;
this.serializationFig = serializationFig;
}
@Override
- public Observable<? extends CollectionIoEvent<MvccEntity>> call(final CollectionIoEvent<MvccEntity> ioevent ) {
+ public Observable<? extends CollectionIoEvent<MvccEntity>>
+ call(final CollectionIoEvent<MvccEntity> ioevent ) {
ValidationUtils.verifyMvccEntityWithEntity( ioevent.getEvent() );
@@ -83,32 +86,33 @@ public class WriteUniqueVerify implements Func1<CollectionIoEvent<MvccEntity>, O
// use simple thread pool to verify fields in parallel
- // We want to use concurrent to fork all validations this way they're wrapped by timeouts and
- // Hystrix thread pools for JMX operations. See the WriteCommand in the EntityCollectionManagerImpl
- // I think it still needs added to the Concurrent utility class
-
+ // We want to use concurrent to fork all validations this way they're wrapped by timeouts
+ // and Hystrix thread pools for JMX operations. See the WriteCommand in the
+ // EntityCollectionManagerImpl.
+ // TODO: still needs to be added to the Concurrent utility class?
final List<Observable<FieldUniquenessResult>> fields =
new ArrayList<Observable<FieldUniquenessResult>>();
-
-
- /**
- * Construct all the functions for verifying we're unique
- */
+ //
+ // Construct all the functions for verifying we're unique
+ //
for ( final Field field : entity.getFields() ) {
- //if it's unique, create a function to validate it and add it to the list of concurrent validations
+ // if it's unique, create a function to validate it and add it to the list of
+ // concurrent validations
if ( field.isUnique() ) {
Observable<FieldUniquenessResult> result =
- Observable.from( field ).subscribeOn( scheduler ).map(new Func1<Field, FieldUniquenessResult>() {
+ Observable.from( field ).subscribeOn( scheduler )
+ .map(new Func1<Field, FieldUniquenessResult>() {
+
@Override
public FieldUniquenessResult call(Field field ) {
// use write-first then read strategy
- UniqueValue written = new UniqueValueImpl( ioevent.getEntityCollection(), field, entity.getId(),
- entity.getVersion() );
+ UniqueValue written = new UniqueValueImpl(
+ ioevent.getEntityCollection(), field, entity.getId(), entity.getVersion() );
// use TTL in case something goes wrong before entity is finally committed
MutationBatch mb = uniqueValueStrat.write( written, serializationFig.getTimeout() );
@@ -138,29 +142,34 @@ public class WriteUniqueVerify implements Func1<CollectionIoEvent<MvccEntity>, O
}
}
- //short circuit. If we zip up nothing, we block forever.
- if(fields.size() == 0){
- return Observable.from(ioevent ).subscribeOn( scheduler );
+ // short circuit. If we zip up nothing, we block forever.
+ if ( fields.isEmpty() ){
+ return Observable.from( ioevent ).subscribeOn( scheduler );
}
- /**
- * Zip the results up
- */
- final FuncN<CollectionIoEvent<MvccEntity>> zipFunction = new FuncN<CollectionIoEvent<MvccEntity>>() {
+ //
+ // Zip the results up
+ //
+ final FuncN<CollectionIoEvent<MvccEntity>> zipFunction =
+ new FuncN<CollectionIoEvent<MvccEntity>>() {
+
@Override
public CollectionIoEvent<MvccEntity> call( final Object... args ) {
- for ( Object resultObj : args ) {
+ Map<String, Field> uniquenessVioloations = new HashMap<String, Field>();
+ for ( Object resultObj : args ) {
FieldUniquenessResult result = ( FieldUniquenessResult ) resultObj;
-
if ( !result.isUnique() ) {
Field field = result.getField();
- throw new WriteUniqueVerifyException(
- "Duplicate field value " + field.getName() + " = " + field.getValue().toString() );
+ uniquenessVioloations.put( field.getName(), field );
}
}
+ if ( !uniquenessVioloations.isEmpty() ) {
+ throw new WriteUniqueVerifyException( uniquenessVioloations );
+ }
+
//return the original event
return ioevent;
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/impl/MvccEntityImplTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/impl/MvccEntityImplTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/impl/MvccEntityImplTest.java
index 36bce42..025b195 100644
--- a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/impl/MvccEntityImplTest.java
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/entity/impl/MvccEntityImplTest.java
@@ -1,17 +1,30 @@
-package org.apache.usergrid.persistence.collection.mvcc.entity.impl;
+/*
+ * 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.entity.impl;
import java.util.UUID;
-
import org.junit.Test;
-
import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntity;
import org.apache.usergrid.persistence.model.entity.Entity;
import org.apache.usergrid.persistence.model.entity.SimpleId;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
-
import com.google.common.base.Optional;
-
import static org.junit.Assert.assertEquals;
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerifyTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerifyTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerifyTest.java
index 1d93ddb..e9b2c7f 100644
--- a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerifyTest.java
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteOptimisticVerifyTest.java
@@ -17,9 +17,13 @@
*/
package org.apache.usergrid.persistence.collection.mvcc.stage.write;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.netflix.astyanax.MutationBatch;
import java.util.ArrayList;
import java.util.List;
import org.apache.usergrid.persistence.collection.CollectionScope;
+import org.apache.usergrid.persistence.collection.exception.WriteOptimisticVerifyException;
import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
import org.apache.usergrid.persistence.collection.mvcc.MvccLogEntrySerializationStrategy;
import org.apache.usergrid.persistence.collection.mvcc.entity.MvccEntity;
@@ -32,13 +36,17 @@ import static org.apache.usergrid.persistence.collection.mvcc.stage.TestEntityGe
import static org.apache.usergrid.persistence.collection.mvcc.stage.TestEntityGenerator.generateEntity;
import org.apache.usergrid.persistence.model.entity.Entity;
import org.apache.usergrid.persistence.model.entity.SimpleId;
+import org.apache.usergrid.persistence.model.field.StringField;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import org.jukito.UseModules;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import rx.Scheduler;
@UseModules( TestCollectionModule.class )
@@ -46,8 +54,14 @@ public class WriteOptimisticVerifyTest extends AbstractMvccEntityStageTest {
@Override
protected void validateStage( final CollectionIoEvent<MvccEntity> event ) {
+
MvccLogEntrySerializationStrategy logstrat = mock( MvccLogEntrySerializationStrategy.class);
- new WriteOptimisticVerify( logstrat ).call( event );
+
+ UniqueValueSerializationStrategy uvstrat = mock( UniqueValueSerializationStrategy.class);
+ Injector injector = Guice.createInjector( new TestCollectionModule() );
+ Scheduler scheduler = injector.getInstance( Scheduler.class );
+
+ new WriteOptimisticVerify( logstrat, uvstrat, scheduler ).call( event );
}
@Test
@@ -60,6 +74,9 @@ public class WriteOptimisticVerifyTest extends AbstractMvccEntityStageTest {
.thenReturn( new SimpleId( UUIDGenerator.newTimeUUID(), "owner" ) );
final Entity entity = generateEntity();
+ entity.setField(new StringField("name", "FOO", true));
+ entity.setField(new StringField("identifier", "BAR", true));
+
final MvccEntity mvccEntity = fromEntity( entity );
List<MvccLogEntry> logEntries = new ArrayList<MvccLogEntry>();
@@ -70,11 +87,16 @@ public class WriteOptimisticVerifyTest extends AbstractMvccEntityStageTest {
MvccLogEntrySerializationStrategy noConflictLog =
mock( MvccLogEntrySerializationStrategy.class );
+
when( noConflictLog.load( collectionScope, entity.getId(), entity.getVersion(), 2) )
.thenReturn( logEntries );
+ UniqueValueSerializationStrategy uvstrat = mock( UniqueValueSerializationStrategy.class);
+ Injector injector = Guice.createInjector( new TestCollectionModule() );
+ Scheduler scheduler = injector.getInstance( Scheduler.class );
+
// Run the stage
- WriteOptimisticVerify newStage = new WriteOptimisticVerify( noConflictLog );
+ WriteOptimisticVerify newStage = new WriteOptimisticVerify( noConflictLog, uvstrat, scheduler );
CollectionIoEvent<MvccEntity> result;
result = newStage.call( new CollectionIoEvent<MvccEntity>( collectionScope, mvccEntity ) );
@@ -95,38 +117,66 @@ public class WriteOptimisticVerifyTest extends AbstractMvccEntityStageTest {
@Test
public void testConflict() throws Exception {
- final CollectionScope collectionScope = mock( CollectionScope.class );
- when( collectionScope.getOrganization() )
+ final CollectionScope scope = mock( CollectionScope.class );
+ when( scope.getOrganization() )
.thenReturn( new SimpleId( UUIDGenerator.newTimeUUID(), "organization" ) );
- when( collectionScope.getOwner() )
+ when( scope.getOwner() )
.thenReturn( new SimpleId( UUIDGenerator.newTimeUUID(), "owner" ) );
+ // there is an entity
final Entity entity = generateEntity();
- final MvccEntity mvccEntity = fromEntity( entity );
+ entity.setField(new StringField("name", "FOO", true));
+ entity.setField(new StringField("identifier", "BAR", true));
+ // log that one operation is active on entity
List<MvccLogEntry> logEntries = new ArrayList<MvccLogEntry>();
logEntries.add( new MvccLogEntryImpl(
entity.getId(), UUIDGenerator.newTimeUUID(), Stage.ACTIVE ));
+
+ // log another operation as active on entity
logEntries.add( new MvccLogEntryImpl(
entity.getId(), UUIDGenerator.newTimeUUID(), Stage.ACTIVE));
- MvccLogEntrySerializationStrategy noConflictLog =
+ // mock up the log
+ MvccLogEntrySerializationStrategy conflictLog =
mock( MvccLogEntrySerializationStrategy.class );
- when( noConflictLog.load( collectionScope, entity.getId(), entity.getVersion(), 2) )
+ when( conflictLog.load( scope, entity.getId(), entity.getVersion(), 2) )
.thenReturn( logEntries );
- // Run the stage
- WriteOptimisticVerify newStage = new WriteOptimisticVerify( noConflictLog );
-
- CollectionIoEvent<MvccEntity> result;
+ // mock up unique values interface
+ UniqueValueSerializationStrategy uvstrat = mock( UniqueValueSerializationStrategy.class);
+ UniqueValue uv1 = new UniqueValueImpl(
+ scope, entity.getField("name"), entity.getId(), entity.getVersion());
+ UniqueValue uv2 = new UniqueValueImpl(
+ scope, entity.getField("identifier"), entity.getId(), entity.getVersion());
+ MutationBatch mb = mock( MutationBatch.class );
+ when( uvstrat.delete(uv1) ).thenReturn(mb);
+ when( uvstrat.delete(uv2) ).thenReturn(mb);
+
+ // use a real scheduler
+ Injector injector = Guice.createInjector( new TestCollectionModule() );
+ Scheduler scheduler = injector.getInstance( Scheduler.class );
+
+ // Run the stage, conflict should be detected
+ final MvccEntity mvccEntity = fromEntity( entity );
boolean conflictDetected = false;
+
+ WriteOptimisticVerify newStage =
+ new WriteOptimisticVerify( conflictLog, uvstrat, scheduler );
+
try {
- result = newStage.call( new CollectionIoEvent<MvccEntity>(collectionScope, mvccEntity));
- } catch (Exception e) {
+ newStage.call( new CollectionIoEvent<MvccEntity>(scope, mvccEntity));
+
+ } catch (WriteOptimisticVerifyException e) {
conflictDetected = true;
}
assertTrue( conflictDetected );
+
+ // check that unique values were deleted
+ verify( uvstrat, times(1) ).delete( uv1 );
+ verify( uvstrat, times(1) ).delete( uv2 );
}
+
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyIT.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyIT.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyIT.java
new file mode 100644
index 0000000..3deb235
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyIT.java
@@ -0,0 +1,97 @@
+/*
+ * 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 org.jukito.JukitoRunner;
+import org.jukito.UseModules;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.apache.usergrid.persistence.collection.CollectionScope;
+import org.apache.usergrid.persistence.collection.cassandra.CassandraRule;
+import org.apache.usergrid.persistence.collection.guice.MigrationManagerRule;
+import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
+import org.apache.usergrid.persistence.model.entity.Entity;
+import com.google.inject.Inject;
+import org.apache.usergrid.persistence.collection.EntityCollectionManager;
+import org.apache.usergrid.persistence.collection.EntityCollectionManagerFactory;
+import org.apache.usergrid.persistence.collection.exception.WriteUniqueVerifyException;
+import org.apache.usergrid.persistence.collection.impl.CollectionScopeImpl;
+import org.apache.usergrid.persistence.collection.mvcc.stage.TestEntityGenerator;
+import org.apache.usergrid.persistence.model.entity.Id;
+import org.apache.usergrid.persistence.model.entity.SimpleId;
+import org.apache.usergrid.persistence.model.field.IntegerField;
+import org.apache.usergrid.persistence.model.field.StringField;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+
+/**
+ * Simple integration test of uniqueness verification.
+ */
+@RunWith( JukitoRunner.class )
+@UseModules( TestCollectionModule.class )
+public class WriteUniqueVerifyIT {
+
+ @ClassRule
+ public static CassandraRule rule = new CassandraRule();
+
+ @Inject
+ @Rule
+ public MigrationManagerRule migrationManagerRule;
+
+ @Inject
+ public EntityCollectionManagerFactory cmf;
+
+ @Test
+ public void testConflict() {
+
+ final Id orgId = new SimpleId("WriteUniqueVerifyIT");
+ final Id appId = new SimpleId("testConflict");
+
+ final CollectionScope scope = new CollectionScopeImpl( appId, orgId, "fastcars" );
+ final EntityCollectionManager entityManager = cmf.createCollectionManager( scope );
+
+ final Entity entity = TestEntityGenerator.generateEntity();
+ entity.setField(new StringField("name", "Aston Martin Vanquish", true));
+ entity.setField(new StringField("identifier", "v12", true));
+ entity.setField(new IntegerField("top_speed_mph", 200));
+ entityManager.write( entity ).toBlockingObservable().last();
+
+ // another enity that tries to use two unique values already taken by first
+ final Entity entity2 = TestEntityGenerator.generateEntity();
+ entity2.setField(new StringField("name", "Aston Martin Vanquish", true));
+ entity2.setField(new StringField("identifier", "v12", true));
+ entity2.setField(new IntegerField("top_speed_mph", 120));
+
+ try {
+ entityManager.write( entity2 ).toBlockingObservable().last();
+ fail("Write should have thrown an exception");
+
+ } catch ( WriteUniqueVerifyException e ) {
+ // verify two unique value violations
+ assertEquals( 2, e.getVioliations().size() );
+ }
+
+ }
+
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyTest.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyTest.java
index a5d360a..6fcbf29 100644
--- a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyTest.java
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/mvcc/stage/write/WriteUniqueVerifyTest.java
@@ -14,22 +14,6 @@
* 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.
- *//*
- * 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;
@@ -60,11 +44,6 @@ import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
-/**
- * TODO: Update the test to correctly test for detecting more than 1 duplicate and exception handling correctly
- *
- * @author tnine
- */
@RunWith( JukitoRunner.class )
@UseModules( TestCollectionModule.class )
public class WriteUniqueVerifyTest {
@@ -96,7 +75,6 @@ public class WriteUniqueVerifyTest {
final CollectionScope collectionScope = mock( CollectionScope.class );
-
// set up the mock to return the entity from the start phase
final Entity entity = generateEntity();
@@ -127,7 +105,6 @@ public class WriteUniqueVerifyTest {
public void testNoFields() {
final CollectionScope collectionScope = mock( CollectionScope.class );
-
// set up the mock to return the entity from the start phase
final Entity entity = generateEntity();
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/util/EntityBuilder.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/util/EntityBuilder.java b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/util/EntityBuilder.java
new file mode 100644
index 0000000..2c53041
--- /dev/null
+++ b/stack/corepersistence/collection/src/test/java/org/apache/usergrid/persistence/collection/util/EntityBuilder.java
@@ -0,0 +1,177 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.usergrid.persistence.model.entity.Entity;
+import org.apache.usergrid.persistence.model.field.BooleanField;
+import org.apache.usergrid.persistence.model.field.DoubleField;
+import org.apache.usergrid.persistence.model.field.EntityObjectField;
+import org.apache.usergrid.persistence.model.field.Field;
+import org.apache.usergrid.persistence.model.field.FloatField;
+import org.apache.usergrid.persistence.model.field.IntegerField;
+import org.apache.usergrid.persistence.model.field.ListField;
+import org.apache.usergrid.persistence.model.field.LocationField;
+import org.apache.usergrid.persistence.model.field.LongField;
+import org.apache.usergrid.persistence.model.field.StringField;
+import org.apache.usergrid.persistence.model.field.value.Location;
+
+
+public class EntityBuilder {
+
+ public static Entity fromMap( String scope, Map<String, Object> item ) {
+ return fromMap( scope, null, item );
+ }
+
+ public static Entity fromMap( String scope, Entity entity, Map<String, Object> map ) {
+
+ if ( entity == null ) {
+ entity = new Entity();
+ }
+
+ for ( String fieldName : map.keySet() ) {
+
+ Object value = map.get( fieldName );
+
+ if ( value instanceof String ) {
+ entity.setField( new StringField( fieldName, (String)value ));
+
+ } else if ( value instanceof Boolean ) {
+ entity.setField( new BooleanField( fieldName, (Boolean)value ));
+
+ } else if ( value instanceof Integer ) {
+ entity.setField( new IntegerField( fieldName, (Integer)value ));
+
+ } else if ( value instanceof Double ) {
+ entity.setField( new DoubleField( fieldName, (Double)value ));
+
+ } else if ( value instanceof Float ) {
+ entity.setField( new FloatField( fieldName, (Float)value ));
+
+ } else if ( value instanceof Long ) {
+ entity.setField( new LongField( fieldName, (Long)value ));
+
+ } else if ( value instanceof List) {
+ entity.setField( listToListField( scope, fieldName, (List)value ));
+
+ } else if ( value instanceof Map ) {
+
+ Field field = null;
+
+ // is the map really a location element?
+ Map<String, Object> m = (Map<String, Object>)value;
+ if ( m.size() == 2) {
+ Double lat = null;
+ Double lon = null;
+ try {
+ if ( m.get("latitude") != null && m.get("longitude") != null ) {
+ lat = Double.parseDouble( m.get("latitude").toString() );
+ lon = Double.parseDouble( m.get("longitude").toString() );
+
+ } else if ( m.get("lat") != null && m.get("lon") != null ) {
+ lat = Double.parseDouble( m.get("lat").toString() );
+ lon = Double.parseDouble( m.get("lon").toString() );
+ }
+ } catch ( NumberFormatException ignored ) {}
+
+ if ( lat != null && lon != null ) {
+ field = new LocationField( fieldName, new Location( lat, lon ));
+ }
+ }
+
+ if ( field == null ) {
+
+ // not a location element, process it as map
+ entity.setField( new EntityObjectField( fieldName,
+ fromMap( scope, (Map<String, Object>)value ))); // recursion
+
+ } else {
+ entity.setField( field );
+ }
+
+ } else {
+ throw new RuntimeException("Unknown type " + value.getClass().getName());
+ }
+ }
+
+ return entity;
+ }
+
+
+ private static ListField listToListField( String scope, String fieldName, List list ) {
+
+ if (list.isEmpty()) {
+ return new ListField( fieldName );
+ }
+
+ Object sample = list.get(0);
+
+ if ( sample instanceof Map ) {
+ return new ListField<Entity>( fieldName, processListForField( scope, list ));
+
+ } else if ( sample instanceof List ) {
+ return new ListField<List>( fieldName, processListForField( scope, list ));
+
+ } else if ( sample instanceof String ) {
+ return new ListField<String>( fieldName, (List<String>)list );
+
+ } else if ( sample instanceof Boolean ) {
+ return new ListField<Boolean>( fieldName, (List<Boolean>)list );
+
+ } else if ( sample instanceof Integer ) {
+ return new ListField<Integer>( fieldName, (List<Integer>)list );
+
+ } else if ( sample instanceof Double ) {
+ return new ListField<Double>( fieldName, (List<Double>)list );
+
+ } else if ( sample instanceof Long ) {
+ return new ListField<Long>( fieldName, (List<Long>)list );
+
+ } else {
+ throw new RuntimeException("Unknown type " + sample.getClass().getName());
+ }
+ }
+
+
+ private static List processListForField( String scope, List list ) {
+ if ( list.isEmpty() ) {
+ return list;
+ }
+ Object sample = list.get(0);
+
+ if ( sample instanceof Map ) {
+ List<Entity> newList = new ArrayList<Entity>();
+ for ( Map<String, Object> map : (List<Map<String, Object>>)list ) {
+ newList.add( fromMap( scope, map ) );
+ }
+ return newList;
+
+ } else if ( sample instanceof List ) {
+ return processListForField( scope, list ); // recursion
+
+ } else {
+ return list;
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/collection/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/stack/corepersistence/collection/src/test/resources/log4j.properties b/stack/corepersistence/collection/src/test/resources/log4j.properties
index f6f50ef..95a0a79 100644
--- a/stack/corepersistence/collection/src/test/resources/log4j.properties
+++ b/stack/corepersistence/collection/src/test/resources/log4j.properties
@@ -1,5 +1,5 @@
# suppress inspection "UnusedProperty" for whole file
-log4j.rootLogger=INFO,stdout
+log4j.rootLogger=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
@@ -11,4 +11,4 @@ log4j.logger.org.safehaus.chop.api.store.amazon=DEBUG
log4j.logger.org.apache.http=ERROR
log4j.logger.com.amazonaws.request=ERROR
-log4j.logger.org.apache.usergrid=DEBUG
+log4j.logger.org.apache.usergrid.persistence.collection=DEBUG
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
index e951098..68d7755 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityCollectionIndexTest.java
@@ -33,6 +33,7 @@ import org.apache.usergrid.persistence.collection.EntityCollectionManagerFactory
import org.apache.usergrid.persistence.collection.cassandra.CassandraRule;
import org.apache.usergrid.persistence.collection.guice.MigrationManagerRule;
import org.apache.usergrid.persistence.collection.impl.CollectionScopeImpl;
+import org.apache.usergrid.persistence.collection.util.EntityBuilder;
import org.apache.usergrid.persistence.collection.util.EntityUtils;
import org.apache.usergrid.persistence.index.EntityCollectionIndex;
import org.apache.usergrid.persistence.index.EntityCollectionIndexFactory;
@@ -43,7 +44,6 @@ import org.apache.usergrid.persistence.model.entity.SimpleId;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import org.apache.usergrid.persistence.query.Query;
import org.apache.usergrid.persistence.query.Results;
-import org.apache.usergrid.persistence.index.legacy.EntityBuilder;
import org.jukito.JukitoRunner;
import org.jukito.UseModules;
import static org.junit.Assert.assertEquals;
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityBuilder.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityBuilder.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityBuilder.java
deleted file mode 100644
index fefb8fb..0000000
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityBuilder.java
+++ /dev/null
@@ -1,177 +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.index.legacy;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import org.apache.usergrid.persistence.model.entity.Entity;
-import org.apache.usergrid.persistence.model.field.BooleanField;
-import org.apache.usergrid.persistence.model.field.DoubleField;
-import org.apache.usergrid.persistence.model.field.EntityObjectField;
-import org.apache.usergrid.persistence.model.field.Field;
-import org.apache.usergrid.persistence.model.field.FloatField;
-import org.apache.usergrid.persistence.model.field.IntegerField;
-import org.apache.usergrid.persistence.model.field.ListField;
-import org.apache.usergrid.persistence.model.field.LocationField;
-import org.apache.usergrid.persistence.model.field.LongField;
-import org.apache.usergrid.persistence.model.field.StringField;
-import org.apache.usergrid.persistence.model.field.value.Location;
-
-
-public class EntityBuilder {
-
- public static Entity fromMap( String scope, Map<String, Object> item ) {
- return fromMap( scope, null, item );
- }
-
- public static Entity fromMap( String scope, Entity entity, Map<String, Object> map ) {
-
- if ( entity == null ) {
- entity = new Entity();
- }
-
- for ( String fieldName : map.keySet() ) {
-
- Object value = map.get( fieldName );
-
- if ( value instanceof String ) {
- entity.setField( new StringField( fieldName, (String)value ));
-
- } else if ( value instanceof Boolean ) {
- entity.setField( new BooleanField( fieldName, (Boolean)value ));
-
- } else if ( value instanceof Integer ) {
- entity.setField( new IntegerField( fieldName, (Integer)value ));
-
- } else if ( value instanceof Double ) {
- entity.setField( new DoubleField( fieldName, (Double)value ));
-
- } else if ( value instanceof Float ) {
- entity.setField( new FloatField( fieldName, (Float)value ));
-
- } else if ( value instanceof Long ) {
- entity.setField( new LongField( fieldName, (Long)value ));
-
- } else if ( value instanceof List) {
- entity.setField( listToListField( scope, fieldName, (List)value ));
-
- } else if ( value instanceof Map ) {
-
- Field field = null;
-
- // is the map really a location element?
- Map<String, Object> m = (Map<String, Object>)value;
- if ( m.size() == 2) {
- Double lat = null;
- Double lon = null;
- try {
- if ( m.get("latitude") != null && m.get("longitude") != null ) {
- lat = Double.parseDouble( m.get("latitude").toString() );
- lon = Double.parseDouble( m.get("longitude").toString() );
-
- } else if ( m.get("lat") != null && m.get("lon") != null ) {
- lat = Double.parseDouble( m.get("lat").toString() );
- lon = Double.parseDouble( m.get("lon").toString() );
- }
- } catch ( NumberFormatException ignored ) {}
-
- if ( lat != null && lon != null ) {
- field = new LocationField( fieldName, new Location( lat, lon ));
- }
- }
-
- if ( field == null ) {
-
- // not a location element, process it as map
- entity.setField( new EntityObjectField( fieldName,
- fromMap( scope, (Map<String, Object>)value ))); // recursion
-
- } else {
- entity.setField( field );
- }
-
- } else {
- throw new RuntimeException("Unknown type " + value.getClass().getName());
- }
- }
-
- return entity;
- }
-
-
- private static ListField listToListField( String scope, String fieldName, List list ) {
-
- if (list.isEmpty()) {
- return new ListField( fieldName );
- }
-
- Object sample = list.get(0);
-
- if ( sample instanceof Map ) {
- return new ListField<Entity>( fieldName, processListForField( scope, list ));
-
- } else if ( sample instanceof List ) {
- return new ListField<List>( fieldName, processListForField( scope, list ));
-
- } else if ( sample instanceof String ) {
- return new ListField<String>( fieldName, (List<String>)list );
-
- } else if ( sample instanceof Boolean ) {
- return new ListField<Boolean>( fieldName, (List<Boolean>)list );
-
- } else if ( sample instanceof Integer ) {
- return new ListField<Integer>( fieldName, (List<Integer>)list );
-
- } else if ( sample instanceof Double ) {
- return new ListField<Double>( fieldName, (List<Double>)list );
-
- } else if ( sample instanceof Long ) {
- return new ListField<Long>( fieldName, (List<Long>)list );
-
- } else {
- throw new RuntimeException("Unknown type " + sample.getClass().getName());
- }
- }
-
-
- private static List processListForField( String scope, List list ) {
- if ( list.isEmpty() ) {
- return list;
- }
- Object sample = list.get(0);
-
- if ( sample instanceof Map ) {
- List<Entity> newList = new ArrayList<Entity>();
- for ( Map<String, Object> map : (List<Map<String, Object>>)list ) {
- newList.add( fromMap( scope, map ) );
- }
- return newList;
-
- } else if ( sample instanceof List ) {
- return processListForField( scope, list ); // recursion
-
- } else {
- return list;
- }
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/29a4966b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
index e8eb5e1..6e52a9e 100644
--- a/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
+++ b/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/legacy/EntityManagerFacade.java
@@ -36,6 +36,7 @@ import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import org.apache.usergrid.persistence.query.EntityRef;
import org.apache.usergrid.persistence.query.Query;
import org.apache.usergrid.persistence.query.Results;
+import org.apache.usergrid.persistence.collection.util.EntityBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;