org.slc.sli.api.resources.util.ResourceUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.slc.sli.api.resources.util.ResourceUtil.java

Source

/*
 * Copyright 2012-2013 inBloom, Inc. and its affiliates.
 *
 * Licensed 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.slc.sli.api.resources.util;

import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slc.sli.api.config.AssociationDefinition;
import org.slc.sli.api.config.EntityDefinition;
import org.slc.sli.api.config.EntityDefinitionStore;
import org.slc.sli.api.constants.PathConstants;
import org.slc.sli.api.constants.ResourceConstants;
import org.slc.sli.api.constants.ResourceNames;
import org.slc.sli.api.representation.EmbeddedLink;
import org.slc.sli.api.representation.EntityBody;
import org.slc.sli.api.security.SLIPrincipal;
import org.slc.sli.validation.schema.ListSchema;
import org.slc.sli.validation.schema.NeutralSchema;
import org.slc.sli.validation.schema.ReferenceSchema;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 * Performs tasks common to both Resource and HomeResource to eliminate code-duplication. These
 * tasks include creating a list of embedded links, adding links to a list regarding associations,
 * and resolving a new URI based on parameters.
 * 
 * @author kmyers <kmyers@wgen.net>
 *
 */
public class ResourceUtil {

    private static final Logger LOG = LoggerFactory.getLogger(ResourceUtil.class);
    private static final String REFERENCE = "REF";
    private static final String LINK = "LINK";
    private static final String BLANK = "";
    private static final Map<String, String> LINK_NAMES = new HashMap<String, String>();
    static {
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.STUDENT_COMPETENCY_OBJECTIVES + LINK,
                "getStudentCompetencyObjectives");
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.STUDENT_COMPETENCY_OBJECTIVES + LINK,
                "getStudentCompetencyObjectives");
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.EDUCATION_ORGANIZATIONS + REFERENCE,
                "getParentEducationOrganization");
        //LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.SCHOOLS + LINK, "getFeederSchools");
        //LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.EDUCATION_ORGANIZATIONS + LINK,
        //"getFeederEducationOrganizations");
        //LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.EDUCATION_ORGANIZATIONS + REFERENCE,
        //"getParentEducationOrganization");
        LINK_NAMES.put(ResourceNames.LEARNINGOBJECTIVES + ResourceNames.LEARNINGOBJECTIVES + REFERENCE,
                "getParentLearningObjective");
        LINK_NAMES.put(ResourceNames.LEARNINGOBJECTIVES + ResourceNames.LEARNINGOBJECTIVES + LINK,
                "getChildLearningObjectives");
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.SCHOOLS + REFERENCE, BLANK);
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.SCHOOLS + LINK, BLANK);
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.EDUCATION_ORGANIZATIONS + LINK, BLANK);
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.SCHOOLS + REFERENCE, BLANK);
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.DISCIPLINE_ACTIONS + "responsibilitySchoolId" + LINK,
                "getDisciplineActionsAsResponsibleSchool");
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.DISCIPLINE_ACTIONS + "assignmentSchoolId" + LINK,
                "getDisciplineActionsAsAssignedSchool");
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.DISCIPLINE_ACTIONS + LINK, BLANK);
        LINK_NAMES.put(ResourceNames.LEARNINGSTANDARDS + ResourceNames.ASSESSMENTS
                + "objectiveAssessment.assessmentItem.learningStandards" + LINK, BLANK);
        LINK_NAMES.put(
                ResourceNames.LEARNINGSTANDARDS + ResourceNames.ASSESSMENTS
                        + "objectiveAssessment.objectiveAssessments.assessmentItem.learningStandards" + LINK,
                BLANK);
        LINK_NAMES.put(ResourceNames.LEARNINGSTANDARDS + ResourceNames.ASSESSMENTS
                + "assessmentItem.learningStandards" + LINK, BLANK);
        LINK_NAMES.put(ResourceNames.LEARNINGOBJECTIVES + ResourceNames.ASSESSMENTS
                + "objectiveAssessment.objectiveAssessments.learningObjectives" + LINK, BLANK);
        LINK_NAMES.put(ResourceNames.LEARNINGOBJECTIVES + ResourceNames.ASSESSMENTS
                + "objectiveAssessment.learningObjectives" + LINK, BLANK);

        //localEducationAgencyReference,educationServiceCenterReference etc will be deprecated after sprint 8.4
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.SCHOOLS
                + "parentEducationAgencyReference" + LINK, "getFeederSchools");
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.SCHOOLS
                + "localEducationAgencyReference" + LINK, "getSchoolsFeedingIntoLEA");
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.SCHOOLS
                + "educationServiceCenterReference" + LINK, "getFeederSchoolsFeedingIntoESC");

        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.EDUCATION_ORGANIZATIONS
                + "parentEducationAgencyReference" + LINK, "getFeederEducationOrganizations");
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.EDUCATION_ORGANIZATIONS
                + "localEducationAgencyReference" + LINK, "getEducationOrganizationsFeedingIntoLEA");
        LINK_NAMES.put(ResourceNames.EDUCATION_ORGANIZATIONS + ResourceNames.EDUCATION_ORGANIZATIONS
                + "educationServiceCenterReference" + LINK, "getEducationOrganizationsFeedingIntoESC");

        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.EDUCATION_ORGANIZATIONS
                + "parentEducationAgencyReference" + REFERENCE, "getParentEducationOrganization");
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.EDUCATION_ORGANIZATIONS
                + "localEducationAgencyReference" + REFERENCE, "getEdOrgsReportingToLEA");
        LINK_NAMES.put(ResourceNames.SCHOOLS + ResourceNames.EDUCATION_ORGANIZATIONS
                + "educationServiceCenterReference" + REFERENCE, "getEdOrgsReportingToESC");
    }

    /**
     * Extracts the API version from the provided URI info.
     * 
     * @param uriInfo
     *            URI requested by user (version is part of the URI)
     * @return version referenced by UriInfo
     */
    public static String getApiVersion(final UriInfo uriInfo) {
        if (uriInfo != null) {
            String uriPath = uriInfo.getPath();
            if (uriPath != null) {
                int indexOfSlash = uriPath.indexOf("/");
                if (indexOfSlash >= 0) {
                    String version = uriPath.substring(0, indexOfSlash);
                    return version;
                } else {
                    return uriPath;
                }
            }
        }

        return null;
    }

    /**
     * Creates a new LinkedList and adds a link for self, then returns that list. When not creating
     * a self link, all other parameters can be null.
     * 
     * @param uriInfo
     *            base URI
     * @param userId
     *            unique identifier of user/object
     * @param defn
     *            entity definition for user/object
     * @param createSelfLink
     *            whether or not to include a self link
     * @return
     */
    @Deprecated
    public static List<EmbeddedLink> getSelfLink(final UriInfo uriInfo, final String userId,
            final EntityDefinition defn) {

        // create a new linkedlist
        LinkedList<EmbeddedLink> links = new LinkedList<EmbeddedLink>();

        // add a "self" link
        if (defn != null) {
            links.add(new EmbeddedLink(ResourceConstants.SELF,
                    ResourceUtil.getURI(uriInfo, defn.getResourceName(), userId).toString()));
        }

        // return
        return links;
    }

    /**
     * Create a self link
     * 
     * @param uriInfo
     *            base URI
     * @param entityId
     *            unique identifier of entity
     * @param defn
     *            entity definition for entity
     * @return the self link
     */
    public static EmbeddedLink getSelfLinkForEntity(final UriInfo uriInfo, final String entityId,
            final EntityDefinition defn) {
        return new EmbeddedLink(ResourceConstants.SELF, getURI(uriInfo, getApiVersion(uriInfo),
                PathConstants.TEMP_MAP.get(defn.getResourceName()), entityId).toString());
    }

    /**
     * Create the custom entity link
     * 
     * @param uriInfo
     *            base uri
     * @param entityId
     *            unique id of the identity
     * @param defn
     *            definition of the entity
     * @return the custom entity link
     */
    public static EmbeddedLink getCustomLink(final UriInfo uriInfo, final String entityId,
            final EntityDefinition defn) {
        return new EmbeddedLink(ResourceConstants.CUSTOM,
                getURI(uriInfo, getApiVersion(uriInfo), PathConstants.TEMP_MAP.get(defn.getResourceName()),
                        entityId, PathConstants.CUSTOM_ENTITIES).toString());
    }

    /**
     * Looks up associations for the given entity (definition) and adds embedded links for each
     * association for the given user ID.
     * 
     * @param entityDefs
     *            all entity definitions
     * @param defn
     *            entity whose associations are being looked up
     * @param links
     *            list to add associations links to
     * @param id
     *            specific ID to append to links to create specific lookup link
     * @param uriInfo
     *            base URI
     */
    @Deprecated
    public static List<EmbeddedLink> getAssociationsLinks(final EntityDefinitionStore entityDefs,
            final EntityDefinition defn, final String id, final UriInfo uriInfo) {

        LinkedList<EmbeddedLink> links = new LinkedList<EmbeddedLink>();

        // look up all associations for supplied entity
        Collection<EntityDefinition> entitiesThatReferenceDefinition = entityDefs.getLinked(defn);

        // loop through all associations to supplied entity type
        for (EntityDefinition definition : entitiesThatReferenceDefinition) {
            if (definition instanceof AssociationDefinition) {
                AssociationDefinition assoc = (AssociationDefinition) definition;
                if (assoc.getSourceEntity().equals(defn)) {
                    links.add(new EmbeddedLink(assoc.getRelNameFromSource(),
                            ResourceUtil.getURI(uriInfo, assoc.getResourceName(), id).toString()));
                    links.add(new EmbeddedLink(assoc.getHoppedTargetLink(),
                            ResourceUtil.getURI(uriInfo, assoc.getResourceName(), id).toString() + "/targets"));
                } else if (assoc.getTargetEntity().equals(defn)) {
                    links.add(new EmbeddedLink(assoc.getRelNameFromTarget(),
                            ResourceUtil.getURI(uriInfo, assoc.getResourceName(), id).toString()));
                    links.add(new EmbeddedLink(assoc.getHoppedSourceLink(),
                            ResourceUtil.getURI(uriInfo, assoc.getResourceName(), id).toString() + "/targets"));
                }
            }
        }
        return links;
    }

    /**
     * Looks up associations for the given entity (definition) and adds embedded links for each
     * association for the given user ID.
     * 
     * @param entityDefs
     *            all entity definitions
     * @param defn
     *            entity whose associations are being looked up
     * @param links
     *            list to add associations links to
     * @param entityBody
     *            object whose links to/from are being requested
     * @param uriInfo
     *            base URI
     */
    public static List<EmbeddedLink> getLinks(final EntityDefinitionStore entityDefs, final EntityDefinition defn,
            final EntityBody entityBody, final UriInfo uriInfo) {

        String id = (String) entityBody.get("id");

        // start with self link
        List<EmbeddedLink> links = new LinkedList<EmbeddedLink>();
        if (defn != null && id != null) {
            links.add(getSelfLinkForEntity(uriInfo, id, defn));
            links.add(getCustomLink(uriInfo, id, defn));

            links.addAll(getReferenceLinks(defn, entityBody, uriInfo, entityDefs));

            if (defn instanceof AssociationDefinition) {
                links.addAll(getLinksForAssociation(uriInfo, id, (AssociationDefinition) defn));
            }

            links.addAll(getLinkedDefinitions(entityDefs, defn, uriInfo, id));

        }

        return links;
    }

    private static List<EmbeddedLink> getLinkedDefinitions(final EntityDefinitionStore entityDefs,
            final EntityDefinition defn, final UriInfo uriInfo, String id) {
        List<EmbeddedLink> links = new LinkedList<EmbeddedLink>();
        // loop through all entities with references to supplied entity type
        for (EntityDefinition definition : entityDefs.getLinked(defn)) {
            EmbeddedLink el;
            // if the entity that has a reference to the defn parameter is an association
            if (definition instanceof AssociationDefinition) {

                AssociationDefinition assoc = (AssociationDefinition) definition;
                if (assoc.getSourceEntity().getStoredCollectionName().equals(defn.getStoredCollectionName())) {
                    String relNameFromSource = assoc.getRelNameFromSource();
                    if (relNameFromSource != null) {
                        el = new EmbeddedLink(relNameFromSource, getURI(uriInfo, getApiVersion(uriInfo),
                                defn.getResourceName(), id, assoc.getResourceName()).toString());
                        links.add(el);
                        LOG.info("Type 1 " + assoc.getRelNameFromSource() + " " + el);
                        if (assoc.getHoppedTargetLink() != null) {
                            el = new EmbeddedLink(assoc.getHoppedTargetLink(),
                                    getURI(uriInfo, getApiVersion(uriInfo), defn.getResourceName(), id,
                                            assoc.getResourceName(), assoc.getTargetEntity().getResourceName())
                                                    .toString());
                            links.add(el);
                            LOG.info("Type 2 " + assoc.getRelNameFromSource() + " " + el);
                        }
                    }

                } else if (assoc.getTargetEntity().getStoredCollectionName()
                        .equals(defn.getStoredCollectionName())) {
                    String relNameFromTarget = assoc.getRelNameFromTarget();
                    if (relNameFromTarget != null) {
                        el = new EmbeddedLink(relNameFromTarget, getURI(uriInfo, getApiVersion(uriInfo),
                                defn.getResourceName(), id, assoc.getResourceName()).toString());
                        links.add(el);
                        LOG.info("Type 3 " + assoc.getRelNameFromSource() + " " + el);
                        if (assoc.getHoppedSourceLink() != null) {
                            el = new EmbeddedLink(assoc.getHoppedSourceLink(),
                                    getURI(uriInfo, getApiVersion(uriInfo), defn.getResourceName(), id,
                                            assoc.getResourceName(), assoc.getSourceEntity().getResourceName())
                                                    .toString());
                            links.add(el);
                            LOG.info("Type 4 " + assoc.getRelNameFromSource() + " " + el);
                        }
                    }
                }
            } else {
                // loop through all reference fields, display as ? links
                for (String referenceFieldName : definition
                        .getReferenceFieldNames(defn.getStoredCollectionName())) {
                    String linkName = getLinkName(defn.getResourceName(), definition.getResourceName(),
                            referenceFieldName, false);
                    if (linkName != null) {
                        if (!linkName.isEmpty()) {
                            el = new EmbeddedLink(linkName,
                                    getURI(uriInfo, getApiVersion(uriInfo), definition.getResourceName()).toString()
                                            + "?" + referenceFieldName + "=" + id);
                            links.add(el);
                            LOG.info("Type 5 " + definition.getResourceName() + " " + el);
                        }
                    }

                }
            }
        }
        return links;
    }

    private static List<EmbeddedLink> getLinksForAssociation(final UriInfo uriInfo, String id,
            AssociationDefinition assoc) {
        List<EmbeddedLink> links = new LinkedList<EmbeddedLink>();

        String sourceLink = ResourceNames.PLURAL_LINK_NAMES.get(assoc.getSourceEntity().getResourceName());
        links.add(
                new EmbeddedLink(sourceLink,
                        getURI(uriInfo, getApiVersion(uriInfo), PathConstants.TEMP_MAP.get(assoc.getResourceName()),
                                id, PathConstants.TEMP_MAP.get(assoc.getSourceEntity().getResourceName()))
                                        .toString()));

        String targetLink = ResourceNames.PLURAL_LINK_NAMES.get(assoc.getTargetEntity().getResourceName());
        links.add(
                new EmbeddedLink(targetLink,
                        getURI(uriInfo, getApiVersion(uriInfo), PathConstants.TEMP_MAP.get(assoc.getResourceName()),
                                id, PathConstants.TEMP_MAP.get(assoc.getTargetEntity().getResourceName()))
                                        .toString()));
        return links;
    }

    private static List<EmbeddedLink> getReferenceLinks(final EntityDefinition defn, final EntityBody entityBody,
            final UriInfo uriInfo, EntityDefinitionStore defnStore) {
        List<EmbeddedLink> links = new LinkedList<EmbeddedLink>();

        if (defn == null || entityBody == null || uriInfo == null) {
            return links;
        }

        // loop through all reference fields on supplied entity type
        for (Entry<String, ReferenceSchema> referenceField : defn.getReferenceFields().entrySet()) {
            // see what GUID is stored in the reference field
            String key = referenceField.getKey();
            if (key.contains(".")) {
                List<EmbeddedLink> embeddedLinks = getEmbeddedReferences(key.split("\\."),
                        referenceField.getValue(), defn, entityBody, uriInfo, defnStore);
                if (embeddedLinks != null) {
                    links.addAll(embeddedLinks);
                }
            } else {
                List<String> guidList = entityBody.getValues(key);
                int count = guidList.size();
                for (String referenceGuid : guidList) {
                    // if a value (GUID) was stored there
                    if (referenceGuid != null) {
                        Set<String> resourceNames = ResourceNames.ENTITY_RESOURCE_NAME_MAPPING
                                .get(referenceField.getValue().getEntityType());
                        if (resourceNames == null) {
                            resourceNames = Collections.emptySet();
                        }
                        count--;
                        if (resourceNames != null) {
                            for (String resourceName : resourceNames) {
                                String linkName = getLinkName(defn.getResourceName(), resourceName, BLANK, true);
                                if (count > 0 && !linkName.isEmpty()) {
                                    linkName = linkName + "[" + count + "]";
                                }
                                if (!linkName.isEmpty()) {
                                    links.add(new EmbeddedLink(linkName,
                                            getURI(uriInfo, getApiVersion(uriInfo), resourceName, referenceGuid)
                                                    .toString()));
                                }

                            }
                        }
                    }
                }
            }
        }
        return links;
    }

    private static List<EmbeddedLink> getEmbeddedReferences(String[] keys, ReferenceSchema ref,
            EntityDefinition defn, Map<String, Object> entityBody, UriInfo uri, EntityDefinitionStore defnStore) {

        EntityDefinition dfn = defnStore.lookupByEntityType(ref.getEntityType());
        if (dfn != null) {
            return getEmbeddedReferences("", Arrays.asList(keys),
                    defnStore.lookupByEntityType(ref.getEntityType()).getResourceName(), defn.getSchema(),
                    entityBody, uri);
        } else {
            LOG.error(String.format(
                    "Failed to generate a link for entity type %s : the definition for the type  was not registered.",
                    ref.getEntityType()));
        }
        return new ArrayList<EmbeddedLink>();
    }

    private static List<EmbeddedLink> getEmbeddedReferences(String prefix, List<String> keys, String resourceName,
            NeutralSchema schema, Map<String, Object> entityBody, UriInfo uri) {
        if (keys.size() == 0) {
            return Collections.emptyList();
        }
        String key = keys.get(0);
        if (keys.size() == 1) {
            Object object = entityBody.get(key);
            if (object == null || (object instanceof Iterable<?> && !((Iterable<?>) object).iterator().hasNext())) {
                return Collections.emptyList();
            }
            String rel = getLinkName(prefix, resourceName, BLANK, true);
            String id = (object instanceof Iterable) ? StringUtils.join((Iterable<?>) object, ",")
                    : object.toString();
            return Arrays.asList(new EmbeddedLink(rel, getVersionedUriString(uri, resourceName, id)));
        } else {
            Object object = entityBody.get(keys.get(0));
            List<EmbeddedLink> results = new ArrayList<EmbeddedLink>();
            if (object instanceof Iterable) {
                for (Object individual : (Iterable<?>) object) {
                    if (individual instanceof Map) {
                        doCreateEmbeddedLink(prefix, keys, resourceName, schema, uri, key, (Map) individual,
                                results);
                    }
                }
                return results;
            } else if (object instanceof Map) {
                doCreateEmbeddedLink(prefix, keys, resourceName, schema, uri, key, (Map) object, results);
                return results;
            }
        }
        return Collections.emptyList();
    }

    // us5975 meetingTime.classPeriod failing to create link
    private static void doCreateEmbeddedLink(String prefix, List<String> keys, String resourceName,
            NeutralSchema schema, UriInfo uri, String key, Map subObject, List<EmbeddedLink> results) {
        NeutralSchema newSchema = schema.getFields().get(key);
        if (newSchema instanceof ListSchema) {
            // warning, complete hack here
            newSchema = ((ListSchema) newSchema).getList().get(0);
        }
        String newPrefix = prefix + (prefix.length() == 0 ? "" : ".") + key + "."
                + getNaturalKey(subObject, newSchema);
        results.addAll(getEmbeddedReferences(newPrefix, keys.subList(1, keys.size()), resourceName, newSchema,
                subObject, uri));
    }

    private static String getNaturalKey(Map<String, Object> object, NeutralSchema schema) {
        for (Entry<String, NeutralSchema> fieldEntry : schema.getFields().entrySet()) {
            NeutralSchema field = fieldEntry.getValue();
            if (field != null) {
                if (field.getAppInfo() != null && field.getAppInfo().isNaturalKey()) {
                    Object obj = object.get(fieldEntry.getKey());
                    if (obj != null) {
                        return obj.toString();
                    }
                }
            }
        }
        return "";
    }

    /**
     * Returns the URI for aggregations
     * 
     * @param uriInfo
     *            The base URI
     * @return A list of links pointing to the base Url for aggregations
     */
    public static List<EmbeddedLink> getAggregateLink(final UriInfo uriInfo) {
        List<EmbeddedLink> links = new ArrayList<EmbeddedLink>();

        links.add(new EmbeddedLink(ResourceConstants.LINKS,
                uriInfo.getBaseUriBuilder().path(ResourceConstants.RESOURCE_PATH_AGG).build().toString()));

        return links;
    }

    /**
     * Adds the value to a list and then puts the list into the query parameters associated to the
     * given key.
     * 
     * @param queryParameters
     *            where to put the value once added to a list
     * @param key
     *            key value for new parameter
     * @param value
     *            resulting value for new parameter
     */
    public static void putValue(MultivaluedMap<String, String> queryParameters, String key, String value) {
        List<String> values = new ArrayList<String>();
        values.add(value);
        queryParameters.put(key, values);
    }

    /**
     * Adds the value to a list and then puts the list into the query parameters associated to the
     * given key.
     * 
     * @param queryParameters
     *            where to put the value once added to a list
     * @param key
     *            key value for new parameter
     * @param value
     *            resulting value for new parameter
     */
    public static void putValue(MultivaluedMap<String, String> queryParameters, String key, int value) {
        ResourceUtil.putValue(queryParameters, key, "" + value);
    }

    /**
     * Helper method to convert MultivaluedMap to a Map
     * 
     * @param map
     * @return
     */
    public static Map<String, String> convertToMap(Map<String, List<String>> map) {
        Map<String, String> results = new HashMap<String, String>();

        if (map != null) {
            for (Map.Entry<String, List<String>> e : map.entrySet()) {
                results.put(e.getKey(), e.getValue().get(0));
            }
        }

        return results;
    }

    /**
     * Returns a URI based on the supplied URI with the paths appended to the base URI.
     * 
     * @param uriInfo
     *            URI of current actions
     * @param paths
     *            Paths that need to be appended
     * @return
     */
    public static URI getURI(UriInfo uriInfo, String... paths) {
        UriBuilder builder = uriInfo.getBaseUriBuilder();

        for (String path : paths) {
            if (path != null) {
                builder.path(path);
            }
        }

        return builder.build();
    }

    public static String getVersionedUriString(UriInfo uriInfo, String... paths) {
        UriBuilder builder = uriInfo.getBaseUriBuilder().path(getApiVersion(uriInfo));

        for (String path : paths) {
            if (path != null) {
                builder.path(path);
            }
        }

        return builder.build().toString();
    }

    /**
     * Analyzes security context to get SLIPrincipal for user.
     * 
     * @return SLIPrincipal from security context
     */
    public static SLIPrincipal getSLIPrincipalFromSecurityContext() {

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (auth instanceof AnonymousAuthenticationToken || auth.getPrincipal() instanceof String
                || !auth.isAuthenticated()) {
            throw new InsufficientAuthenticationException("Login Required");
        }

        // lookup security/login information
        SLIPrincipal principal = (SLIPrincipal) auth.getPrincipal();
        return principal;
    }

    /**
     * Finds the link name based on the entity type and the reference entity name
     * 
     * @param resourceName
     *            Entity name for which the links are generated
     * @param referenceName
     *            Referenced entity name
     * @param referenceField
     *            Referenced field Name
     * @param isReferenceEntity
     *            indicates whether its a referenced entity
     * @return
     */
    public static String getLinkName(String resourceName, String referenceName, String referenceField,
            boolean isReferenceEntity) {

        String linkName = "";
        String key = resourceName + referenceName;
        String keyWithRefField = key + referenceField + LINK;
        if (isReferenceEntity) {
            key = key + REFERENCE;
        } else {
            key = key + LINK;
        }

        if (LINK_NAMES.containsKey(key)) {
            linkName = LINK_NAMES.get(key);
        } else if (LINK_NAMES.containsKey(keyWithRefField)) {
            linkName = LINK_NAMES.get(keyWithRefField);
        } else if (isReferenceEntity) {
            linkName = ResourceNames.SINGULAR_LINK_NAMES.get(referenceName);
        } else {
            linkName = ResourceNames.PLURAL_LINK_NAMES.get(referenceName);
        }
        return linkName;
    }

}