Update the KVM resource endpoints to be more client friendly.
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 87a8649..489ffdf 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
@@ -290,8 +290,11 @@
public <A extends Entity> A create( String entityType, Class<A> entityClass, Map<String, Object> properties )
throws Exception {
- if ( ( entityType != null ) && ( entityType.startsWith( TYPE_ENTITY ) || entityType
- .startsWith( "entities" ) ) ) {
+ if ( ( entityType != null ) &&
+ ( entityType.startsWith( TYPE_ENTITY ) || entityType.startsWith( "entities" )
+ // safeguard against creating entities with type keyvaluemaps since we have specific Usergrid
+ // keyvaluemap implementation
+ || entityType.startsWith( "keyvaluemaps" ) || entityType.startsWith( "keyvaluemap" )) ) {
throw new IllegalArgumentException( "Invalid entity type" );
}
A e = null;
diff --git a/stack/core/src/main/java/org/apache/usergrid/system/UsergridFeatures.java b/stack/core/src/main/java/org/apache/usergrid/system/UsergridFeatures.java
index 22ba48c..2826f66 100644
--- a/stack/core/src/main/java/org/apache/usergrid/system/UsergridFeatures.java
+++ b/stack/core/src/main/java/org/apache/usergrid/system/UsergridFeatures.java
@@ -63,7 +63,7 @@
public static boolean isKvmFeatureEnabled(){
- return getFeaturesEnabled().contains(Feature.KVM);
+ return true;
}
}
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java
index 228598c..e73277c 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java
@@ -148,8 +148,8 @@
return getEventsResource( ui );
}
- //@RequireApplicationAccess
- @Path("maps")
+ @RequireApplicationAccess
+ @Path("keyvaluemaps")
public KvmResource getKvmResource(@Context UriInfo ui ) throws Exception {
return getSubResource( KvmResource.class );
}
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/kvm/KvmResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/kvm/KvmResource.java
index 264f968..4d6107e 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/kvm/KvmResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/kvm/KvmResource.java
@@ -43,9 +43,7 @@
@Component("org.apache.usergrid.rest.applications.kvm.KvmResource")
@Scope("prototype")
-@Produces({ MediaType.APPLICATION_JSON, "application/javascript", "application/x-javascript", "text/ecmascript",
- "application/ecmascript", "text/jscript"
-})
+@Produces(MediaType.APPLICATION_JSON)
public class KvmResource extends AbstractContextResource {
private static final Logger logger = LoggerFactory.getLogger( KvmResource.class );
@@ -87,26 +85,34 @@
throw new IllegalArgumentException("Only 1 map can be created at a time.");
}
+ enforceQueryFeature(ui);
+
final String mapName = json.keySet().iterator().next();
- final Object meta = json.get(mapName);
- if( !(meta instanceof Map) ){
+
+ if( !(json.get(mapName) instanceof Map) ){
throw new IllegalArgumentException("New map details must be provided as a JSON object.");
}
+ final Map<String, Object> meta = (Map<String, Object>)json.get(mapName);
if(StringUtils.isEmpty(mapName)){
throw new IllegalArgumentException("Property mapName is required.");
}
+ if( json.containsKey("metadata") ){
+ json.remove("metadata");
+ }
+
final String appMap = services.getApplicationId().toString();
final MapScope mapScope = new MapScopeImpl(services.getApplication().asId(), appMap);
final MapManagerFactory mmf = injector.getInstance(MapManagerFactory.class);
final MapManager mapManager = mmf.createMapManager(mapScope);
final Map<String, Object> mapDetails = new HashMap<String, Object>(){{
-
- put("active", true);
- put("modified", System.currentTimeMillis() );
- put("details", meta);
+ put("metadata", new HashMap<String, Object>(){{
+ put("active", true);
+ put("modified", System.currentTimeMillis() );
+ }});
+ putAll(meta);
}};
@@ -121,7 +127,7 @@
response.setAction( "post" );
response.setApplication( services.getApplication() );
response.setParams( ui.getQueryParameters() );
- response.setProperty("maps", Collections.singletonList(map));
+ response.setProperty("maps", map);
return response;
@@ -135,6 +141,7 @@
@QueryParam("cursor") String cursor) {
limit = validateLimit(limit);
+ enforceQueryFeature(ui);
final String appMap = services.getApplicationId().toString();
@@ -144,14 +151,12 @@
MapKeyResults mapKeyResults = mapManager.getKeys(cursor, limit );
- List<Map<String, Object>> results = new ArrayList<>();
+ Map<String, Object> results = new HashMap<>();
Observable.from(mapKeyResults.getKeys()).flatMap(key -> {
- return Observable.just(new HashMap<String, Object>() {{
- put(key, JsonUtils.parse(mapManager.getString(key)));
- }});
+ return Observable.just(results.put(key, JsonUtils.parse(mapManager.getString(key))));
- }).doOnNext(entry -> results.add(entry)).toBlocking().lastOrDefault(null);
+ }).toBlocking().lastOrDefault(null);
ApiResponse response = createApiResponse();
@@ -177,6 +182,7 @@
@PathParam("mapName") String mapName ) {
limit = validateLimit(limit);
+ enforceQueryFeature(ui);
final String appMap = services.getApplicationId().toString();
@@ -193,7 +199,7 @@
response.setAction( "get" );
response.setApplication( services.getApplication() );
response.setParams( ui.getQueryParameters() );
- response.setProperty("maps", Collections.singletonList(map));
+ response.setProperty("maps", map);
return response;
@@ -205,7 +211,7 @@
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public ApiResponse createEntries( @Context UriInfo ui,
- List<Map<String,Object>> json,
+ Map<String,Object> json,
@PathParam("mapName") String mapName ) {
if ( json.size() > BATCH_SIZE_MAX ){
@@ -216,19 +222,17 @@
throw new IllegalArgumentException("Property mapName is required.");
}
+ enforceQueryFeature(ui);
+
final MapScope mapScope = new MapScopeImpl(services.getApplication().asId(), mapName);
final MapManagerFactory mmf = injector.getInstance(MapManagerFactory.class);
final MapManager mapManager = mmf.createMapManager(mapScope);
//TODO maybe RX flatmap this or parallel stream
- json.forEach( item -> {
-
- String key = item.keySet().iterator().next();
- Object value = item.get(key);
+ json.forEach( (key, value) -> {
mapManager.putString(key, value.toString());
-
});
@@ -236,7 +240,6 @@
response.setAction( "post" );
response.setApplication( services.getApplication() );
response.setParams( ui.getQueryParameters() );
- response.setProperty("mapName", mapName);
response.setProperty("entries", json);
return response;
@@ -257,6 +260,7 @@
}
limit = validateLimit(limit);
+ enforceQueryFeature(ui);
final MapScope mapScope = new MapScopeImpl(services.getApplication().asId(), mapName);
final MapManagerFactory mmf = injector.getInstance(MapManagerFactory.class);
@@ -264,7 +268,6 @@
MapKeyResults mapKeyResults = mapManager.getKeys(cursor, limit );
-
ApiResponse response = createApiResponse();
response.setAction( "get" );
response.setApplication( services.getApplication() );
@@ -292,6 +295,7 @@
}
limit = validateLimit(limit);
+ enforceQueryFeature(ui);
final MapScope mapScope = new MapScopeImpl(services.getApplication().asId(), mapName);
final MapManagerFactory mmf = injector.getInstance(MapManagerFactory.class);
@@ -299,11 +303,10 @@
MapKeyResults mapKeyResults = mapManager.getKeys(cursor, limit );
- List<Map<String, String>> results = new ArrayList<>();
+ Map<String, Object> results = new HashMap<>();
Observable.from(mapKeyResults.getKeys()).flatMap(key ->{
- return Observable.just(new HashMap<String, String>(){{put(key, mapManager.getString(key));}});
-
- }).doOnNext(entry -> results.add(entry)).toBlocking().lastOrDefault(null);
+ return Observable.just(results.put(key, mapManager.getString(key)));
+ }).toBlocking().lastOrDefault(null);
ApiResponse response = createApiResponse();
@@ -323,27 +326,34 @@
@GET
@Path("{mapName}/entries/{keyName}")
@Produces(MediaType.APPLICATION_JSON)
- public ApiResponse getEntry( @Context UriInfo ui,
+ public Object getEntry( @Context UriInfo ui,
@PathParam("mapName") String mapName,
- @PathParam("keyName") String keyName ) {
+ @PathParam("keyName") String keyName,
+ @QueryParam("rawData") @DefaultValue("false") boolean rawData) {
+ enforceQueryFeature(ui);
final MapScope mapScope = new MapScopeImpl(services.getApplication().asId(), mapName);
final MapManagerFactory mmf = injector.getInstance(MapManagerFactory.class);
final MapManager mapManager = mmf.createMapManager(mapScope);
- List<Map<String, String>> results = new ArrayList<>();
- results.add(new HashMap<String, String>(){{put(keyName, mapManager.getString(keyName));}});
+ Map<String, Object> results = new HashMap<>();
+ Object value = mapManager.getString(keyName);
+ results.put(keyName, value);
+
+ if( !rawData ) {
+ ApiResponse response = createApiResponse();
+ response.setAction("get");
+ response.setApplication(services.getApplication());
+ response.setParams(ui.getQueryParameters());
+ response.setProperty("entries", results);
+ return response;
+ }else{
+ return value;
+ }
- ApiResponse response = createApiResponse();
- response.setAction( "get" );
- response.setApplication( services.getApplication() );
- response.setParams( ui.getQueryParameters() );
- response.setProperty("entries", results);
-
- return response;
}
@@ -354,5 +364,15 @@
}
+ private void enforceQueryFeature(UriInfo ui) {
+
+ if( StringUtils.isNotEmpty(ui.getQueryParameters().getFirst("ql"))){
+
+ throw new IllegalArgumentException("Query feature not supported for keyvaluemaps");
+
+ }
+
+ }
+
}