org.openmrs.module.webservices.rest.resource.BaseRestDataResource.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.webservices.rest.resource.BaseRestDataResource.java

Source

/*
 * The contents of this file are subject to the OpenMRS Public 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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.webservices.rest.resource;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.OpenmrsData;
import org.openmrs.OpenmrsObject;
import org.openmrs.api.context.Context;
import org.openmrs.module.openhmis.commons.api.entity.IEntityDataService;
import org.openmrs.module.openhmis.commons.api.f.Action2;
import org.openmrs.module.webservices.rest.web.RequestContext;
import org.openmrs.module.webservices.rest.web.representation.DefaultRepresentation;
import org.openmrs.module.webservices.rest.web.representation.FullRepresentation;
import org.openmrs.module.webservices.rest.web.representation.RefRepresentation;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.openmrs.module.webservices.rest.web.resource.impl.AlreadyPaged;
import org.openmrs.module.webservices.rest.web.resource.impl.DataDelegatingCrudResource;
import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingResourceDescription;
import org.openmrs.module.webservices.rest.web.resource.impl.NeedsPaging;
import org.openmrs.module.webservices.rest.web.resource.impl.ServiceSearcher;
import org.springframework.beans.BeanUtils;

/**
 * REST resource for {@link org.openmrs.OpenmrsData} entities.
 * @param <E> The model class
 */
public abstract class BaseRestDataResource<E extends OpenmrsData> extends DataDelegatingCrudResource<E>
        implements IEntityDataServiceResource<E> {
    private static final Log LOG = LogFactory.getLog(BaseRestDataResource.class);

    private Class<E> entityClass = null;

    /**
     * Syncs the base collection with the items in the sync collection. This will add any missing items, updating existing
     * items, and delete any items not found in the sync collection.
     * @param base The collection to update.
     * @param sync The collection used to update the base.
     * @param <E> The {@link OpenmrsObject} stored in the collection.
     */
    public static <E extends OpenmrsObject> void syncCollection(Collection<E> base, Collection<E> sync) {
        syncCollection(base, sync, new Action2<Collection<E>, E>() {
            @Override
            public void apply(Collection<E> collection, E entity) {
                collection.add(entity);
            }
        }, new Action2<Collection<E>, E>() {
            @Override
            public void apply(Collection<E> collection, E entity) {
                collection.remove(entity);
            }
        });
    }

    public static <E extends OpenmrsObject> void syncCollection(Collection<E> base, Collection<E> sync,
            Action2<Collection<E>, E> add, Action2<Collection<E>, E> remove) {
        Map<String, E> baseMap = new HashMap<String, E>(base.size());
        Map<String, E> syncMap = new HashMap<String, E>(sync.size());
        for (E item : base) {
            baseMap.put(item.getUuid(), item);
        }
        for (E item : sync) {
            syncMap.put(item.getUuid(), item);
        }

        for (E item : baseMap.values()) {
            if (syncMap.containsKey(item.getUuid())) {
                // Update the existing item
                E syncItem = syncMap.get(item.getUuid());
                syncItem.setId(item.getId());

                BeanUtils.copyProperties(syncItem, item);
            } else {
                // Delete item that is not in the sync collection
                remove.apply(base, item);
            }
        }

        for (E item : syncMap.values()) {
            if (!baseMap.containsKey(item.getUuid())) {
                // Add the item not in the base collection
                add.apply(base, item);
            }
        }
    }

    @Override
    public abstract E newDelegate();

    @Override
    public abstract Class<? extends IEntityDataService<E>> getServiceClass();

    @Override
    public E save(E delegate) {
        return getService().save(delegate);
    }

    @Override
    public DelegatingResourceDescription getRepresentationDescription(Representation rep) {
        DelegatingResourceDescription description = new DelegatingResourceDescription();
        description.addProperty("uuid");
        description.addProperty("display", findMethod("getDisplayString"));

        if (!(rep instanceof RefRepresentation)) {
            description.addProperty("voided");
            description.addProperty("voidReason");

            if (rep instanceof FullRepresentation) {
                description.addProperty("auditInfo", findMethod("getAuditInfo"));
            }
        }

        return description;
    }

    @Override
    public DelegatingResourceDescription getCreatableProperties() {
        DelegatingResourceDescription description = getRepresentationDescription(new DefaultRepresentation());
        description.removeProperty("uuid");
        description.removeProperty("voidReason");

        return description;
    }

    public String getDisplayString(E instance) {
        return instance.getClass().getSimpleName();
    }

    @Override
    public E getByUniqueId(String uniqueId) {
        if (StringUtils.isEmpty(uniqueId)) {
            return null;
        }

        return getService().getByUuid(uniqueId);
    }

    @Override
    protected void delete(E delegate, String reason, RequestContext context) {
        getService().voidEntity(delegate, reason);
    }

    @Override
    public void purge(E delegate, RequestContext context) {
        getService().purge(delegate);
    }

    @Override
    protected NeedsPaging<E> doGetAll(RequestContext context) {
        return new NeedsPaging<E>(getService().getAll(), context);
    }

    @Override
    protected AlreadyPaged<E> doSearch(RequestContext context) {
        String query = context.getRequest().getParameter("q");

        return new ServiceSearcher<E>(this.getServiceClass(), "getResources", "getCountOfResources").search(query,
                context);
    }

    /**
     * Gets a usable instance of the actual class of the generic type E defined by the implementing sub-class.
     * @return The class object for the entity.
     */
    @SuppressWarnings("unchecked")
    public Class<E> getEntityClass() {
        if (entityClass == null) {
            ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();

            entityClass = (Class) parameterizedType.getActualTypeArguments()[0];
        }

        return entityClass;
    }

    protected IEntityDataService<E> getService() {
        return Context.getService(getServiceClass());
    }
}