Add collection version testing and new _version endpoint to retrieve the version for a collection.
Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/b6d14069 Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/b6d14069 Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/b6d14069 Branch: refs/heads/collectionDelete Commit: b6d14069aa500530d5b86112efd732031e52b0e8 Parents: 221b99d Author: Mike Dunker <[email protected]> Authored: Mon Jul 17 14:54:31 2017 -0700 Committer: Mike Dunker <[email protected]> Committed: Mon Jul 17 14:54:31 2017 -0700 ---------------------------------------------------------------------- .../usergrid/corepersistence/CoreModule.java | 2 +- .../corepersistence/CpEntityManager.java | 17 +- .../corepersistence/CpEntityManagerFactory.java | 6 +- .../index/CollectionClearService.java | 35 ++++ .../index/CollectionClearServiceImpl.java | 69 +++++++ .../index/CollectionDeleteService.java | 30 ---- .../index/CollectionDeleteServiceImpl.java | 57 ------ .../index/CollectionVersionManagerImpl.java | 4 +- .../usergrid/persistence/EntityManager.java | 4 +- .../org/apache/usergrid/persistence/Query.java | 18 +- .../index/CollectionVersionTest.java | 32 ---- .../persistence/index/query/Identifier.java | 3 +- .../rest/applications/CollectionResource.java | 58 +++++- .../collection/CollectionClearTest.java | 179 +++++++++++++++++++ 14 files changed, 374 insertions(+), 140 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java index 5515abd..6a93af5 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java @@ -143,7 +143,7 @@ public class CoreModule extends AbstractModule { bind( ReIndexService.class ).to( ReIndexServiceImpl.class ); - bind( CollectionDeleteService.class ).to( CollectionDeleteServiceImpl.class ); + bind( CollectionClearService.class ).to( CollectionClearServiceImpl.class ); bind( ExportService.class ).to( ExportServiceImpl.class ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManager.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManager.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManager.java index a76720d..e192939 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManager.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManager.java @@ -158,7 +158,7 @@ public class CpEntityManager implements EntityManager { private EntityCollectionManager ecm; public QueueManagerFactory queueManagerFactory; - private CollectionDeleteService collectionDeleteService; + private CollectionClearService collectionClearService; private CollectionVersionManagerFactory collectionVersionManagerFactory; @@ -187,7 +187,7 @@ public class CpEntityManager implements EntityManager { final CollectionSettingsFactory collectionSettingsFactory, final UUID applicationId, final QueueManagerFactory queueManagerFactory, - final CollectionDeleteService collectionDeleteService, + final CollectionClearService collectionClearService, final CollectionVersionManagerFactory collectionVersionManagerFactory) { this.entityManagerFig = entityManagerFig; @@ -255,7 +255,7 @@ public class CpEntityManager implements EntityManager { this.skipAggregateCounters = false; this.queueManagerFactory = queueManagerFactory; - this.collectionDeleteService = collectionDeleteService; + this.collectionClearService = collectionClearService; this.collectionVersionManagerFactory = collectionVersionManagerFactory; } @@ -1890,9 +1890,16 @@ public class CpEntityManager implements EntityManager { } @Override - public void deleteCollection( String collectionName ){ + public void clearCollection(String collectionName ){ - collectionDeleteService.deleteCollection(applicationId, collectionName); + collectionClearService.clearCollection(applicationId, collectionName); + + } + + @Override + public String getCollectionVersion(String collectionName ){ + + return collectionClearService.getCollectionVersion(applicationId, collectionName); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java index b3dac57..2e3b180 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java @@ -117,7 +117,7 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application private final CollectionSettingsFactory collectionSettingsFactory; private ActorSystemManager actorSystemManager; private final LockManager lockManager; - private final CollectionDeleteService collectionDeleteService; + private final CollectionClearService collectionClearService; private final CollectionVersionManagerFactory collectionVersionManagerFactory; private final QueueManagerFactory queueManagerFactory; @@ -143,7 +143,7 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application this.collectionService = injector.getInstance( CollectionService.class ); this.connectionService = injector.getInstance( ConnectionService.class ); this.collectionSettingsFactory = injector.getInstance( CollectionSettingsFactory.class ); - this.collectionDeleteService = injector.getInstance( CollectionDeleteService.class ); + this.collectionClearService = injector.getInstance( CollectionClearService.class ); this.collectionVersionManagerFactory = injector.getInstance( CollectionVersionManagerFactory.class ); Properties properties = cassandraService.getProperties(); @@ -395,7 +395,7 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application collectionSettingsFactory, applicationId, queueManagerFactory, - collectionDeleteService, + collectionClearService, collectionVersionManagerFactory); return em; http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearService.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearService.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearService.java new file mode 100644 index 0000000..76380e5 --- /dev/null +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearService.java @@ -0,0 +1,35 @@ +/* + * 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.corepersistence.index; + +import java.util.UUID; + +public interface CollectionClearService { + + /** + * Clear the entities from the current version of a collection by changing the collection version and queueing up a delete of the old entities + */ + void clearCollection(final UUID applicationID, final String baseCollectionName); + + /** + * Get the current version of a collection + */ + String getCollectionVersion(final UUID applicationID, final String baseCollectionName); +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearServiceImpl.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearServiceImpl.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearServiceImpl.java new file mode 100644 index 0000000..ff64d6a --- /dev/null +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionClearServiceImpl.java @@ -0,0 +1,69 @@ +/* + * 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.corepersistence.index; + +import com.google.inject.Inject; +import org.apache.usergrid.corepersistence.asyncevents.AsyncEventService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.UUID; + +public class CollectionClearServiceImpl implements CollectionClearService { + private static final Logger logger = LoggerFactory.getLogger(CollectionClearServiceImpl.class ); + + private CollectionVersionManagerFactory collectionVersionManagerFactory; + private AsyncEventService asyncEventService; + + @Inject + public CollectionClearServiceImpl( + final CollectionVersionManagerFactory collectionVersionManagerFactory, + final AsyncEventService asyncEventService + ) + { + this.collectionVersionManagerFactory = collectionVersionManagerFactory; + this.asyncEventService = asyncEventService; + } + + @Override + public void clearCollection(final UUID applicationID, final String baseCollectionName) { + CollectionScope scope = new CollectionScopeImpl(applicationID, baseCollectionName); + CollectionVersionManager collectionVersionManager = collectionVersionManagerFactory.getInstance(scope); + + // change version + String oldVersion = collectionVersionManager.updateCollectionVersion(); + logger.info("Collection cleared: appID:{} baseCollectionName:{} oldVersion:{} newVersion:{}", + applicationID.toString(), baseCollectionName, oldVersion, collectionVersionManager.getCollectionVersion(false)); + + // queue up delete of old version entities + asyncEventService.queueCollectionDelete(scope, oldVersion); + } + + @Override + public String getCollectionVersion(UUID applicationID, String baseCollectionName) { + CollectionScope scope = new CollectionScopeImpl(applicationID, baseCollectionName); + CollectionVersionManager collectionVersionManager = collectionVersionManagerFactory.getInstance(scope); + + String currentVersion = collectionVersionManager.getCollectionVersion(true); + + return currentVersion; + } + +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteService.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteService.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteService.java deleted file mode 100644 index 85b8fed..0000000 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.corepersistence.index; - -import java.util.UUID; - -public interface CollectionDeleteService { - - /** - * Delete the current version of a collection by changing the collection version and queueing up a delete of the old entities - */ - void deleteCollection(final UUID applicationID, final String baseCollectionName); -} http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteServiceImpl.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteServiceImpl.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteServiceImpl.java deleted file mode 100644 index 5c64079..0000000 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionDeleteServiceImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.corepersistence.index; - -import com.google.inject.Inject; -import org.apache.usergrid.corepersistence.asyncevents.AsyncEventService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.UUID; - -public class CollectionDeleteServiceImpl implements CollectionDeleteService { - private static final Logger logger = LoggerFactory.getLogger(CollectionDeleteServiceImpl.class ); - - private CollectionVersionManagerFactory collectionVersionManagerFactory; - private AsyncEventService asyncEventService; - - @Inject - public CollectionDeleteServiceImpl( - final CollectionVersionManagerFactory collectionVersionManagerFactory, - final AsyncEventService asyncEventService - ) - { - this.collectionVersionManagerFactory = collectionVersionManagerFactory; - this.asyncEventService = asyncEventService; - } - - @Override - public void deleteCollection(final UUID applicationID, final String baseCollectionName) { - CollectionScope scope = new CollectionScopeImpl(applicationID, baseCollectionName); - CollectionVersionManager collectionVersionManager = collectionVersionManagerFactory.getInstance(scope); - - // change version - String oldVersion = collectionVersionManager.updateCollectionVersion(); - - // queue up delete of old version entities - asyncEventService.queueCollectionDelete(scope, oldVersion); - } - -} http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionVersionManagerImpl.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionVersionManagerImpl.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionVersionManagerImpl.java index 7ed557c..c5bb417 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionVersionManagerImpl.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/CollectionVersionManagerImpl.java @@ -95,7 +95,7 @@ public class CollectionVersionManagerImpl implements CollectionVersionManager { } String oldCollectionVersion = getCollectionVersion(true); - String newCollectionVersion = getNewCollectionVersion(); + String newCollectionVersion = generateNewCollectionVersion(); mapManager.putLong(MAP_PREFIX_LAST_CHANGED+collectionName, System.currentTimeMillis()); mapManager.putString(MAP_PREFIX_VERSION+collectionName, newCollectionVersion); cache.put(scope, newCollectionVersion); @@ -104,7 +104,7 @@ public class CollectionVersionManagerImpl implements CollectionVersionManager { return oldCollectionVersion; } - private static String getNewCollectionVersion() { + private static String generateNewCollectionVersion() { return UUIDGenerator.newTimeUUID().toString(); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManager.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManager.java b/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManager.java index a977f31..f55263d 100644 --- a/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManager.java +++ b/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManager.java @@ -530,7 +530,9 @@ public interface EntityManager { Object getCollectionSettings( String collectionName ); - void deleteCollection( String collectionName ); + void clearCollection(String collectionName); + + String getCollectionVersion(String collectionName); public void grantRolePermission( String roleName, String permission ) throws Exception; http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/main/java/org/apache/usergrid/persistence/Query.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/Query.java b/stack/core/src/main/java/org/apache/usergrid/persistence/Query.java index 900bda5..5662f06 100644 --- a/stack/core/src/main/java/org/apache/usergrid/persistence/Query.java +++ b/stack/core/src/main/java/org/apache/usergrid/persistence/Query.java @@ -31,6 +31,8 @@ import org.apache.usergrid.persistence.index.query.tree.Operand; import org.apache.usergrid.persistence.index.utils.ClassUtils; import org.apache.usergrid.persistence.index.utils.ListUtils; import org.apache.usergrid.persistence.index.utils.MapUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.Serializable; @@ -41,7 +43,7 @@ import java.util.Map.Entry; public class Query { - + private static final Logger logger = LoggerFactory.getLogger(Query.class); public enum Level { @@ -319,6 +321,13 @@ public class Query { public static Query fromIdentifier( Object id ) { + if (id == null) { + throw new IllegalArgumentException("null identifier passed in"); + } + Identifier objectIdentifier = Identifier.from(id); + if (objectIdentifier == null) { + throw new IllegalArgumentException("Supplied id results in null Identifier"); + } Query q = new Query(); q.addIdentifier( Identifier.from(id) ); return q; @@ -409,6 +418,10 @@ public class Query { } for ( Identifier identifier : identifiers ) { + if (identifier == null) { + logger.error("containsUuidIdentifiersOnly(): identifier in identifiers list is null"); + return false; + } if ( !identifier.isUUID() ) { return false; } @@ -635,6 +648,9 @@ public class Query { if ( identifiers == null ) { identifiers = new ArrayList<Identifier>(); } + if (identifier == null) { + throw new IllegalArgumentException("adding null identifier is not allowed"); + } identifiers.add( identifier ); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/core/src/test/java/org/apache/usergrid/corepersistence/index/CollectionVersionTest.java ---------------------------------------------------------------------- diff --git a/stack/core/src/test/java/org/apache/usergrid/corepersistence/index/CollectionVersionTest.java b/stack/core/src/test/java/org/apache/usergrid/corepersistence/index/CollectionVersionTest.java deleted file mode 100644 index a3c7284..0000000 --- a/stack/core/src/test/java/org/apache/usergrid/corepersistence/index/CollectionVersionTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.corepersistence.index; - -import org.junit.runner.RunWith; -import net.jcip.annotations.NotThreadSafe; -import org.apache.usergrid.corepersistence.TestIndexModule; -import org.apache.usergrid.persistence.core.test.UseModules; -import org.apache.usergrid.persistence.index.impl.EsRunner; - -@RunWith( EsRunner.class ) -@UseModules( { TestIndexModule.class } ) -@NotThreadSafe -public class CollectionVersionTest { -} http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Identifier.java ---------------------------------------------------------------------- diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Identifier.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Identifier.java index 84a28f0..70d2284 100644 --- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Identifier.java +++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/query/Identifier.java @@ -34,6 +34,7 @@ public class Identifier implements Serializable { public static final String UUID_REX = "[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"; public static final String EMAIL_REX = "[a-zA-Z0-9._%'+\\-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"; + public static final String NAME_REX = "[a-zA-Z0-9_\\-./'+ ]*"; public enum Type { UUID, NAME, EMAIL @@ -46,7 +47,7 @@ public class Identifier implements Serializable { static Pattern emailRegEx = Pattern.compile( EMAIL_REX ); // "Pattern nameRegEx" below used to be [a-zA-Z0-9_\\-./], changed it to contain a 'space' to a // ddress https://issues.apache.org/jira/browse/USERGRID-94 - static Pattern nameRegEx = Pattern.compile( "[a-zA-Z0-9_\\-./'+ ]*" ); + static Pattern nameRegEx = Pattern.compile( NAME_REX ); private Identifier( Type type, Object value ) { http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/rest/src/main/java/org/apache/usergrid/rest/applications/CollectionResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/CollectionResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/CollectionResource.java index 0ab0661..86b3216 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/CollectionResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/CollectionResource.java @@ -51,6 +51,8 @@ import org.apache.usergrid.services.ServicePayload; import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; @@ -75,7 +77,7 @@ public class CollectionResource extends ServiceResource { @POST - @Path("{itemName}/clear") + @Path("{itemName}/_clear") @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) @RequireApplicationAccess public ApiResponse executeClearCollection( @@ -84,16 +86,16 @@ public class CollectionResource extends ServiceResource { @QueryParam(CONFIRM_COLLECTION_NAME) String confirmCollectionName) throws Exception { if (logger.isTraceEnabled()){ - logger.trace( "CollectionResource.executeDeleteOnCollection" ); + logger.trace( "CollectionResource.executeClearCollection" ); } - if (!Application.isCustomCollectionName(itemName.toString())) { + if (!Application.isCustomCollectionName(itemName.getPath())) { throw new IllegalArgumentException( "Cannot clear built-in collections (" + itemName + ")." ); } - if (!itemName.toString().equals(confirmCollectionName)) { + if (!itemName.getPath().equals(confirmCollectionName)) { throw new IllegalArgumentException( "Cannot delete collection without supplying correct collection name in query parameter " + CONFIRM_COLLECTION_NAME ); @@ -103,7 +105,7 @@ public class CollectionResource extends ServiceResource { UUID applicationId = getApplicationId(); - emf.getEntityManager(applicationId).deleteCollection(itemName.toString()); + emf.getEntityManager(applicationId).clearCollection(itemName.getPath()); if (logger.isTraceEnabled()) { logger.trace("CollectionResource.executeDeleteOnCollection() deleted, appId={} collection={}", @@ -111,12 +113,54 @@ public class CollectionResource extends ServiceResource { } ApiResponse response = createApiResponse(); - response.setAction("delete"); + response.setAction("post"); response.setApplication(emf.getEntityManager( applicationId ).getApplication()); response.setParams(ui.getQueryParameters()); if (logger.isTraceEnabled()) { - logger.trace("CollectionResource.executeDeleteOnCollection() sending response"); + logger.trace("CollectionResource.executeClearCollection() sending response"); + } + + return response; + + } + + @GET + @Path( "{itemName}/_version") + @Produces({MediaType.APPLICATION_JSON,"application/javascript"}) + @RequireApplicationAccess + @JSONP + public ApiResponse executeGetCollectionVersion( + @Context UriInfo ui, + @PathParam("itemName") PathSegment itemName, + @QueryParam("callback") @DefaultValue("callback") String callback ) throws Exception { + + if (logger.isTraceEnabled()){ + logger.trace( "CollectionResource.executeGetCollectionVersion" ); + } + + if (!Application.isCustomCollectionName(itemName.getPath())) { + throw new IllegalArgumentException( + "Built-in collections are not versioned." + ); + } + + addItemToServiceContext( ui, itemName ); + + UUID applicationId = getApplicationId(); + + String currentVersion = emf.getEntityManager(applicationId).getCollectionVersion(itemName.getPath()); + + ApiResponse response = createApiResponse(); + response.setAction("get"); + response.setApplication(emf.getEntityManager( applicationId ).getApplication()); + Map<String,Object> data = new HashMap<>(); + data.put("collectionName",itemName.getPath()); + data.put("version",currentVersion); + response.setData(data); + + if (logger.isTraceEnabled()) { + logger.trace("CollectionResource.executeGetCollectionVersion() sending response"); } return response; http://git-wip-us.apache.org/repos/asf/usergrid/blob/b6d14069/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/CollectionClearTest.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/CollectionClearTest.java b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/CollectionClearTest.java new file mode 100644 index 0000000..e40c193 --- /dev/null +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/CollectionClearTest.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.rest.applications.collection; + + +import org.apache.usergrid.rest.test.resource.AbstractRestIT; +import org.apache.usergrid.rest.test.resource.model.ApiResponse; +import org.apache.usergrid.rest.test.resource.model.Collection; +import org.apache.usergrid.rest.test.resource.model.Entity; +import org.apache.usergrid.rest.test.resource.model.QueryParameters; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +import static org.junit.Assert.*; + +/** + * Tests collection clear functionality. + */ + +public class CollectionClearTest extends AbstractRestIT { + + private static final Logger logger = LoggerFactory.getLogger(CollectionClearTest.class); + + + /** + * Tests collection clear functionality. + * @throws Exception + */ + @Test + public void collectionDelete() throws Exception { + + String collectionName = "children"; + int numEntities = 10; + String namePrefix = "child"; + + int numEntitiesAfterClear = 5; + String namePrefixAfterClear = "abc"; + + // verify collection version is empty + ApiResponse tempResponse = this.app().collection(collectionName).collection("_version").get().getResponse(); + LinkedHashMap dataMap = (LinkedHashMap)tempResponse.getData(); + assertEquals("", dataMap.get("version")); + assertEquals(collectionName, dataMap.get("collectionName")); + + createEntities( collectionName, namePrefix, numEntities ); + + // retrieve entities, provide 1 more than num entities + QueryParameters parms = new QueryParameters().setLimit( numEntities + 1 ).setQuery("order by created asc"); + List<Entity> entities = retrieveEntities(collectionName, namePrefix, parms, numEntities, false); + assertEquals(numEntities, entities.size()); + + // clear the collection + Map<String, Object> payload = new HashMap<String, Object>(); + parms = new QueryParameters().setKeyValue("confirm_collection_name", collectionName); + tempResponse = this.app().collection(collectionName).collection("_clear").post(true, payload, parms); + + // verify collection version has changed + tempResponse = this.app().collection(collectionName).collection("_version").get().getResponse(); + dataMap = (LinkedHashMap)tempResponse.getData(); + String newVersion = (String)dataMap.get("version"); + assertNotEquals("", newVersion); + assertEquals(collectionName, dataMap.get("collectionName")); + + // validate that 0 entities left + List<Entity> entitiesAfterClear = retrieveEntities(collectionName, namePrefix, parms, 0, true); + assertEquals(0, entitiesAfterClear.size()); + + // insert more entities using same collectionName + createEntities( collectionName, namePrefixAfterClear, numEntitiesAfterClear ); + + // validate correct number of entities + parms = new QueryParameters().setLimit( numEntitiesAfterClear + 1 ).setQuery("order by created asc"); + List<Entity> newEntities = retrieveEntities(collectionName, namePrefixAfterClear, parms, numEntitiesAfterClear, false); + assertEquals(numEntitiesAfterClear, newEntities.size()); + + // verify collection version has not changed + tempResponse = this.app().collection(collectionName).collection("_version").get().getResponse(); + dataMap = (LinkedHashMap)tempResponse.getData(); + assertEquals(newVersion, dataMap.get("version")); + assertEquals(collectionName, dataMap.get("collectionName")); + } + + + /** + * Creates a number of entities with sequential names going up to the numOfEntities and posts them to the + * collection specified with collectionName. + * @param collectionName + * @param numOfEntities + */ + public List<Entity> createEntities(String collectionName, String namePrefix, int numOfEntities ){ + List<Entity> entities = new LinkedList<>( ); + + for ( int i = 1; i <= numOfEntities; i++ ) { + Map<String, Object> entityPayload = new HashMap<String, Object>(); + entityPayload.put( "name", namePrefix + String.valueOf( i ) ); + entityPayload.put( "num", i ); + + Entity entity = new Entity( entityPayload ); + + entities.add( entity ); + + this.app().collection( collectionName ).post( entity ); + + if ( i % 100 == 0){ + logger.info("created {} entities", i); + } + } + logger.info("created {} total entities", numOfEntities); + + this.waitForQueueDrainAndRefreshIndex(); + + return entities; + } + + /** + * Retrieves a specified number of entities from a collection. + * @param collectionName + * @param parms + * @param numOfEntities + */ + public List<Entity> retrieveEntities(String collectionName, String namePrefix, QueryParameters parms, int numOfEntities, boolean reverseOrder){ + List<Entity> entities = new LinkedList<>( ); + Collection testCollection = this.app().collection( collectionName ).get(parms, true); + + int entityNum; + if (reverseOrder) { + entityNum = numOfEntities; + } else { + entityNum = 1; + } + while (testCollection.getCursor() != null) { + while (testCollection.hasNext()) { + Entity returnedEntity = testCollection.next(); + assertEquals(namePrefix + String.valueOf(entityNum), returnedEntity.get("name")); + entities.add(returnedEntity); + if (reverseOrder) { + entityNum--; + } else { + entityNum++; + } + } + + testCollection = this.app().collection(collectionName).getNextPage(testCollection, parms, true); + } + + // handle left over entities + while (testCollection.hasNext()) { + Entity returnedEntity = testCollection.next(); + assertEquals(namePrefix + String.valueOf(entityNum), returnedEntity.get("name")); + entities.add(returnedEntity); + if (reverseOrder) { + entityNum--; + } else { + entityNum++; + } + } + + assertEquals(entities.size(), numOfEntities); + return entities; + } + +}
