package com.evrythng.java.wrapper.service; import com.evrythng.commons.domain.SortOrder; import com.evrythng.java.wrapper.ApiManager; import com.evrythng.java.wrapper.core.EvrythngApiBuilder.Builder; import com.evrythng.java.wrapper.core.EvrythngServiceBase; import com.evrythng.java.wrapper.core.http.Status; import com.evrythng.java.wrapper.exception.EvrythngClientException; import com.evrythng.thng.resource.model.store.Collection; import com.evrythng.thng.resource.model.store.Thng; import com.evrythng.thng.resource.model.store.action.Action; import com.evrythng.thng.resource.model.store.action.CustomAction; import com.fasterxml.jackson.core.type.TypeReference; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import org.pcollections.PVector; /** * Service wrapper for the {@code /collections} endpoint of the EVRYTHNG API. */ public class CollectionService extends EvrythngServiceBase { public static final String PATH_COLLECTIONS = "/collections"; public static final String PATH_COLLECTION = PATH_COLLECTIONS + "/%s"; public static final String PATH_COLLECTION_THNGS = PATH_COLLECTION + "/thngs"; public static final String PATH_COLLECTION_THNG = PATH_COLLECTION_THNGS + "/%s"; public static final String PATH_COLLECTION_ACTIONS = PATH_COLLECTION + "/actions"; public static final String PATH_COLLECTION_ALL_ACTIONS = PATH_COLLECTION_ACTIONS + "/all"; public static final String PATH_COLLECTION_TYPED_ACTIONS = PATH_COLLECTION_ACTIONS + "/%s"; public static final String PATH_COLLECTION_TYPED_ACTION = PATH_COLLECTION_TYPED_ACTIONS + "/%s"; public static final String PATH_CHILDREN_COLLECTIONS = PATH_COLLECTION + "/collections"; public static final String PATH_CHILD_COLLECTION = PATH_CHILDREN_COLLECTIONS + "/%s"; private static final TypeReference<List<Action>> ACTIONS_TYPE_REFERENCE = new TypeReference<List<Action>>() {}; public CollectionService(final ApiManager apiManager) { super(apiManager); } /* ***** /collections ***** */ /** * Creates a new {@link Collection}. * <p> * POST {@value #PATH_COLLECTIONS} * * @param collection the instant holding the {@link Collection} resource data * @return a {@link Collection} creator */ public Builder<Collection> collectionCreator(final Collection collection) throws EvrythngClientException { return post(PATH_COLLECTIONS, collection, new TypeReference<Collection>() { }); } /** * Retrieves the last updated {@link Collection} resources. * <p> * GET {@value #PATH_COLLECTIONS} * * @return a preconfigured {@link Builder} */ public Builder<List<Collection>> collectionsReader() throws EvrythngClientException { return get(PATH_COLLECTIONS, new TypeReference<List<Collection>>() { }); } /* ***** /collections/{id} ***** */ /** * Retrieves the referenced {@link Collection}. * <p> * GET {@value #PATH_COLLECTION} * * @param collectionId collection id * @return a preconfigured {@link Builder} */ public Builder<Collection> collectionReader(final String collectionId) throws EvrythngClientException { return get(String.format(PATH_COLLECTION, collectionId), new TypeReference<Collection>() { }); } /** * Updates the referenced {@link Collection}. * <p> * PUT {@value #PATH_COLLECTION} * * @param collectionId collection id * @param collection {@link Collection} instance * @return a preconfigured {@link Builder} */ public Builder<Collection> collectionUpdater(final String collectionId, final Collection collection) throws EvrythngClientException { return put(String.format(PATH_COLLECTION, collectionId), collection, new TypeReference<Collection>() { }); } /** * Deletes the referenced {@link Collection}. * <p> * DELETE {@value #PATH_COLLECTION} * * @param collectionId collection id * @return a preconfigured {@link Builder} */ public Builder<Boolean> collectionDeleter(final String collectionId) throws EvrythngClientException { return delete(String.format(PATH_COLLECTION, collectionId)); } /* ***** /collections/{id}/thngs ***** */ /** * Retrieves the last updated {@link Thng} resources linked with the * referenced {@link Collection}. * <p> * GET {@value #PATH_COLLECTION_THNGS} * * @param collectionId collection id * @return a preconfigured {@link Builder} */ public Builder<List<Thng>> thngsReader(final String collectionId) throws EvrythngClientException { return get(String.format(PATH_COLLECTION_THNGS, collectionId), new TypeReference<List<Thng>>() { }); } /** * Adds the referenced {@link Thng} to the provided {@link Collection}. * <p> * PUT {@value #PATH_COLLECTION_THNGS} * * @param collectionId collection id * @param thngId thng id * @return a preconfigured {@link Builder} * @see #thngsAdder(String, List) */ public Builder<Collection> thngAdder(final String collectionId, final String thngId) throws EvrythngClientException { return thngsAdder(collectionId, Collections.singletonList(thngId)); } /** * Adds the referenced {@link Thng} resources to the provided * {@link Collection}. * <p> * PUT {@value #PATH_COLLECTION_THNGS} * * @param collectionId collection id * @param thngs list of thng ids * @return a preconfigured {@link Builder} */ public Builder<Collection> thngsAdder(final String collectionId, final List<String> thngs) throws EvrythngClientException { return put(String.format(PATH_COLLECTION_THNGS, collectionId), thngs, new TypeReference<Collection>() { }); } /* ***** /collections/{id}/thngs/{id} ***** */ /** * Removes the referenced {@link Thng} from the provided {@link Collection}. * <p> * DELETE {@value #PATH_COLLECTION_THNG} * * @param collectionId collection id * @param thngId thng id * @return a preconfigured {@link Builder} */ public Builder<Boolean> thngRemover(final String collectionId, final String thngId) throws EvrythngClientException { return delete(String.format(PATH_COLLECTION_THNG, collectionId, thngId)); } /** * Removes all {@link Thng} resources from the provided {@link Collection}. * <p> * DELETE {@value #PATH_COLLECTION_THNGS} * * @param collectionId collection id * @return a preconfigured {@link Builder} */ public Builder<Boolean> thngsRemover(final String collectionId) throws EvrythngClientException { return delete(String.format(PATH_COLLECTION_THNGS, collectionId)); } protected void checkCustomType(final String customType) { if (!customType.startsWith("_")) { throw new IllegalArgumentException("Custom types must start with '_' (underscore)."); } } public <T extends Action> Builder<T> actionCreator(final String collectionId, final T actionToCreate) throws EvrythngClientException { return (Builder<T>) post(String.format(PATH_COLLECTION_TYPED_ACTIONS, collectionId, actionToCreate.getType()), actionToCreate, new TypeReference<Action>() { }); } public Builder<CustomAction> actionReader(final String collectionId, final String customType, final String actionId) throws EvrythngClientException { checkCustomType(customType); return get(String.format(PATH_COLLECTION_TYPED_ACTION, collectionId, customType, actionId), new TypeReference<CustomAction>() { }); } public Builder<List<CustomAction>> actionsReader(final String collectionId, final String customType) throws EvrythngClientException { checkCustomType(customType); return get(String.format(PATH_COLLECTION_TYPED_ACTIONS, collectionId, customType), new TypeReference<List<CustomAction>>() { }); } private static void notBlank(final String target, final String targetName) { if (target == null || target.isEmpty()) { throw new IllegalArgumentException(targetName + " cannot be blank"); } } private static void notNull(final Object target, final String targetName) { if (target == null) { throw new IllegalArgumentException(targetName + " cannot be null"); } } /** * Removes all children {@link Collection}s from the provided {@link Collection}. * <p> * DELETE {@value #PATH_CHILDREN_COLLECTIONS} */ public Builder<Boolean> childrenCollectionsRemover(final String collectionId) throws EvrythngClientException { notBlank(collectionId, "collectionId"); return delete(String.format(PATH_CHILDREN_COLLECTIONS, collectionId)); } /** * Removes the provided child {@link Collection} from the provided {@link Collection}. * <p> * DELETE {@value #PATH_CHILD_COLLECTION} */ public Builder<Boolean> childCollectionRemover(final String collectionId, final String childCollectionId) throws EvrythngClientException { notBlank(collectionId, "collectionId"); notBlank(childCollectionId, "childCollectionId"); return delete(String.format(PATH_CHILD_COLLECTION, collectionId, childCollectionId)); } /** * Adds children {@link Collection}s matching the provided ids to the provided {@link Collection}. * <p> * POST {@value #PATH_CHILDREN_COLLECTIONS} */ public Builder<Void> childrenCollectionsAdder(final String collectionId, final Set<String> childrenCollectionsId) throws EvrythngClientException { notBlank(collectionId, "collectionId"); notNull(childrenCollectionsId, "childrenCollectionsId"); for (String id : childrenCollectionsId) { notBlank(id, "childCollectionId"); } return post(String.format(PATH_CHILDREN_COLLECTIONS, collectionId), childrenCollectionsId, Status.OK, new TypeReference<Void>() { }); } /** * Adds child {@link Collection} matching the provided id to the provided {@link Collection}. * <p> * POST {@value #PATH_CHILDREN_COLLECTIONS} */ public Builder<Void> childCollectionAdder(final String collectionId, final String childCollectionId) throws EvrythngClientException { notBlank(collectionId, "collectionId"); notBlank(childCollectionId, "childCollectionId"); return childrenCollectionsAdder(collectionId, Collections.singleton(childCollectionId)); } /** * Retrieves all children {@link Collection}s for the provided {@link Collection}. * <p> * GET {@value #PATH_CHILDREN_COLLECTIONS} */ public Builder<List<Collection>> childrenCollectionsReader(final String collectionId) throws EvrythngClientException { notBlank(collectionId, "collectionId"); return get(String.format(PATH_CHILDREN_COLLECTIONS, collectionId), new TypeReference<List<Collection>>() { }); } /** * Retrieves all actions of collection. * @param collectionId collection id. */ public Builder<Iterator<PVector<Action>>> actionsIterator(final String collectionId) { return iterator(String.format(PATH_COLLECTION_ALL_ACTIONS, collectionId), ACTIONS_TYPE_REFERENCE).sortOrder( SortOrder.descending()); } /** * Retrieves all actions of collection of type. * @param collectionId collection id. * @param actionTypeName action type. */ public Builder<Iterator<PVector<Action>>> actionsIterator(final String collectionId, final String actionTypeName) { return iterator(String.format(PATH_COLLECTION_TYPED_ACTIONS, collectionId, actionTypeName), ACTIONS_TYPE_REFERENCE).sortOrder(SortOrder.descending()); } }