package com.apigee.sdk.data.client.entities; import com.apigee.sdk.data.client.ApigeeDataClient; import com.apigee.sdk.data.client.ApigeeDataClient.Query; import com.apigee.sdk.data.client.response.ApiResponse; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; /** * Models a collection of entities as a local object. Collections * are the primary way that entities are organized in API BaaS. * * @see <a href="http://apigee.com/docs/app-services/content/collections">Collections documentation</a> */ public class Collection { private ApigeeDataClient dataClient; private String type; private Map<String,Object> qs; private ArrayList<Entity> list; private int iterator; private ArrayList<String> previous; private String next; private String cursor; /** * Default constructor for a Collection object. * * @param dataClient an instance of the DataClient class * @param type the entity 'type' associated with the colleciton * @param qs optional Map object of query parameters to apply to the collection retrieval */ public Collection(ApigeeDataClient dataClient, String type, Map<String,Object> qs) { this.dataClient = dataClient; this.type = type; if( qs == null ) { this.qs = new HashMap<String,Object>(); } else { this.qs = qs; } this.list = new ArrayList<Entity>(); this.iterator = -1; this.previous = new ArrayList<String>(); this.next = null; this.cursor = null; this.fetch(); } /** * Gets the entity 'type' associated with the collection. * * @return the collection type */ public String getType(){ return this.type; } /** * Sets the entity 'type' associated with the collection. * * @param type the collection type */ public void setType(String type){ this.type = type; } /** * Retrieves the current state of the collection from the server, and populates * an the Collection object with the returned set of entities. Executes synchronously. * * @return an ApiResponse object */ public ApiResponse fetch() { if (this.cursor != null) { this.qs.put("cursor", this.cursor); } Query query = this.dataClient.queryEntitiesRequest("GET", this.qs, null, this.dataClient.getOrganizationId(), this.dataClient.getApplicationId(), this.type); ApiResponse response = query.getResponse(); if (response.getError() != null) { this.dataClient.writeLog("Error getting collection."); } else { String theCursor = response.getCursor(); int count = response.getEntityCount(); UUID nextUUID = response.getNext(); if( nextUUID != null ) { this.next = nextUUID.toString(); } else { this.next = null; } this.cursor = theCursor; this.saveCursor(theCursor); if ( count > 0 ) { this.resetEntityPointer(); this.list = new ArrayList<Entity>(); List<Entity> retrievedEntities = response.getEntities(); for ( Entity retrievedEntity : retrievedEntities ) { if( retrievedEntity.getUuid() != null ) { retrievedEntity.setType(this.type); this.list.add(retrievedEntity); } } } } return response; } /** * Adds an entity to the Collection object. * * @param entityData a Map object of entity properties to be saved in the entity * @return an Entity object that represents the newly added entity. Must include * a 'type' property. Executes synchronously. */ public Entity addEntity(Map<String,Object> entityData) { Entity entity = null; ApiResponse response = this.dataClient.createEntity(entityData); if( (response != null) && (response.getError() == null) && (response.getEntityCount() > 0) ) { entity = response.getFirstEntity(); if (entity != null) { this.list.add(entity); } } return entity; } /** * Deletes the provided entity on the server, then updates the * Collection object by calling fetch(). Executes synchronously. * * @param entity an Entity object that contains a 'type' and 'uuid' property */ public ApiResponse destroyEntity(Entity entity) { ApiResponse response = entity.destroy(); if (response.getError() != null) { this.dataClient.writeLog("Could not destroy entity."); } else { response = this.fetch(); } return response; } /** * Retrieves an entity from the server. * * @param uuid the UUID of the entity to retrieve * @return an ApiResponse object */ public ApiResponse getEntityByUuid(UUID uuid) { Entity entity = new Entity(this.dataClient); entity.setType(this.type); entity.setUuid(uuid); return entity.fetch(); } /** * Gets the list of entities in the Collection object. * * @return the list of entities */ public ArrayList<Entity> getList() { return this.list; } /** * Gets the first entity in the Collection object. * * @return an Entity object */ public Entity getFirstEntity() { return ((this.list.size() > 0) ? this.list.get(0) : null); } /** * Gets the last entity in the Collection object. * * @return an Entity object */ public Entity getLastEntity() { return ((this.list.size() > 0) ? this.list.get(this.list.size()-1) : null); } /** * Checks if there is another entity in the Collection after the current pointer position. * * @return Boolean true/false */ public boolean hasNextEntity() { int next = this.iterator + 1; return ((next >= 0) && (next < this.list.size())); } /** * Checks if there is an entity in the Collection before the current pointer position. * * @return Boolean true/false */ public boolean hasPrevEntity() { int prev = this.iterator - 1; return ((prev >= 0) && (prev < this.list.size())); } /** * Checks if there is an entity in the Collection after the current * pointer position, and returns it. * * @return an Entity object */ public Entity getNextEntity() { if (this.hasNextEntity()) { this.iterator++; return this.list.get(this.iterator); } return null; } /** * Checks if there is an entity in the Collection before the current * pointer position, and returns it. * * @return an Entity object */ public Entity getPrevEntity() { if (this.hasPrevEntity()) { this.iterator--; return this.list.get(this.iterator); } return null; } /** * Resets the pointer to the start of the Collection. */ public void resetEntityPointer() { this.iterator = -1; } /** * Saves a pagination cursor. */ public void saveCursor(String cursor) { this.next = cursor; } /** * Clears the currently saved pagination cursor from the Collection. */ public void resetPaging() { this.previous.clear(); this.next = null; this.cursor = null; } /** * Checks if a pagination cursor for the next result set is * present in the Collection. * * @return Boolean true/false */ public boolean hasNextPage() { return this.next != null; } /** * Checks if a pagination cursor for the previous result set is * present in the Collection * * @return Boolean true/false */ public boolean hasPrevPage() { return !this.previous.isEmpty(); } /** * Checks if a pagination cursor for the next result set is * present in the Collection, then fetches it. * * @return an ApiResponse object if a cursor is present, otherwise null */ public ApiResponse getNextPage() { if (this.hasNextPage()) { this.previous.add(this.cursor); this.cursor = this.next; this.list.clear(); return this.fetch(); } return null; } /** * Checks if a pagination cursor for the previous result set is * present in the Collection, then fetches it. * * @return an ApiResponse object if a cursor is present, otherwise null */ public ApiResponse getPrevPage() { if (this.hasPrevPage()) { this.next = null; int indexOfLastObject = this.previous.size() - 1; this.cursor = this.previous.get(indexOfLastObject); this.previous.remove(indexOfLastObject); this.list.clear(); return this.fetch(); } return null; } }