Package org.apache.wink.server.internal.utils

Source Code of org.apache.wink.server.internal.utils.SystemLinksBuilderImpl

/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.wink.server.internal.utils;

import java.net.URI;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;

import org.apache.wink.common.RestConstants;
import org.apache.wink.common.internal.registry.metadata.MethodMetadata;
import org.apache.wink.common.internal.utils.MediaTypeUtils;
import org.apache.wink.common.model.atom.AtomConstants;
import org.apache.wink.common.model.synd.SyndLink;
import org.apache.wink.server.internal.handlers.FindRootResourceHandler;
import org.apache.wink.server.handlers.MessageContext;
import org.apache.wink.server.internal.registry.ResourceInstance;
import org.apache.wink.server.internal.registry.ResourceRecord;
import org.apache.wink.server.internal.registry.SubResourceInstance;
import org.apache.wink.server.utils.SystemLinksBuilder;

public class SystemLinksBuilderImpl extends AbstractLinksBuilderImpl<SystemLinksBuilder> implements
    SystemLinksBuilder {

    private LinkType[] types;
    private boolean    allResources;

    public SystemLinksBuilderImpl(MessageContext context) {
        super(context);
        types = null;
        allResources = isContinuedSearchMode();
    }

    protected boolean isContinuedSearchMode() {
        return Boolean.valueOf(context.getProperties()
            .getProperty(FindRootResourceHandler.SEARCH_POLICY_CONTINUED_SEARCH_KEY, "false")); //$NON-NLS-1$
    }

    public SystemLinksBuilder types(LinkType... types) {
        this.types = types;
        return this;
    }

    public SystemLinksBuilder allResources(boolean all) {
        allResources = all;
        return this;
    }

    @Override
    public List<SyndLink> build(List<SyndLink> out) {

        Set<SyndLink> set = new HashSet<SyndLink>();

        // if the search mode is "Continued Search" we need to generate links
        // for all
        // of the matching root resources and not just for the current one
        if (allResources) {
            // get the path to use for obtaining the matching root resources
            URI uri = UriBuilder.fromPath(resourcePath).buildFromEncodedMap(pathParams);
            String path = uri.toString();
            List<ResourceInstance> rootResources = registry.getMatchingRootResources(path);
            // go over all the root matching resources and generate links for
            // them
            for (ResourceInstance rootResource : rootResources) {
                UriBuilder uriBuilder = initUriBuilder(path);
                ResourceRecord record = rootResource.getRecord();
                build(set, uriBuilder, record);
            }
        } else {
            // generate links just for this one resource
            UriBuilder uriBuilder = initUriBuilder();
            build(set, uriBuilder, record);
        }

        if (out == null) {
            out = new LinkedList<SyndLink>();
        }

        out.addAll(set);

        return out;
    }

    private Set<SyndLink> build(Set<SyndLink> set, UriBuilder selfUriBuilder, ResourceRecord record) {
        List<MethodMetadata> methods = null;
        if (subResourcePath != null && subResourcePath.length() > 0) {
            // 1) find all the sub-resources that match the sub-resource path
            List<SubResourceInstance> subResources =
                record.getMatchingSubResourceMethods(subResourcePath);
            methods = new LinkedList<MethodMetadata>();
            for (SubResourceInstance sub : subResources) {
                methods.add(sub.getMetadata());
            }
            // 2) add the sub-resource path to the uri builder
            selfUriBuilder.path(subResourcePath);
        } else {
            methods = record.getMetadata().getResourceMethods();
        }
        return build(set, selfUriBuilder, methods);
    }

    private Set<SyndLink> build(Set<SyndLink> set,
                                UriBuilder selfUriBuilder,
                                List<MethodMetadata> methods) {
        // add all query parameters to the self uri
        for (String query : queryParams.keySet()) {
            selfUriBuilder.queryParam(query, queryParams.get(query).toArray());
        }

        // get a set of the required links to generate
        Set<LinkType> systemLinksToGenerate = generateSystemLinksSet();

        // self link; should not be created if wasn't requested.
        // self link; not replace it if some already exists
        URI selfUri = selfUriBuilder.buildFromEncodedMap(pathParams);
        if (systemLinksToGenerate.contains(LinkType.SELF) && getLink(set,
                                                                     AtomConstants.ATOM_REL_SELF) == null) {
            set.add(createLink(AtomConstants.ATOM_REL_SELF, null, selfUri));
        }

        // edit link; should not be created if wasn't requested.
        // edit link if the Resource has an update operation; does not replace
        // it if it already
        // exists
        if (systemLinksToGenerate.contains(LinkType.EDIT) && getLink(set,
                                                                     AtomConstants.ATOM_REL_EDIT) == null) {
            for (MethodMetadata methodRecord : methods) {
                String httpMethod = methodRecord.getHttpMethod();
                if (httpMethod.equalsIgnoreCase(HttpMethod.PUT) || httpMethod
                    .equalsIgnoreCase(HttpMethod.DELETE)) {
                    set.add(createLink(AtomConstants.ATOM_REL_EDIT, null, selfUri));
                    break;
                }
            }
        }

        // alternate links - all GET operations
        Set<MediaType> producedTypesForGet = getProducedTypesForGet(methods);
        for (MediaType mediaType : producedTypesForGet) {
            if (addAltParam && queryParams.get(RestConstants.REST_PARAM_MEDIA_TYPE) == null) {
                selfUriBuilder.replaceQueryParam(RestConstants.REST_PARAM_MEDIA_TYPE,
                                                 MediaTypeUtils.toEncodedString(mediaType));
            }
            URI href = selfUriBuilder.buildFromEncodedMap(pathParams);
            if (MediaTypeUtils.equalsIgnoreParameters(mediaType, MediaTypeUtils.OPENSEARCH_TYPE)) {
                if (systemLinksToGenerate.contains(LinkType.OPENSEARCH)) {
                    // open search link; should not be created if wasn't
                    // requested.
                    set.add(createLink(AtomConstants.ATOM_REL_SEARCH, mediaType, href));
                }
            } else if (systemLinksToGenerate.contains(LinkType.ALTERNATE)) {
                set.add(createLink(AtomConstants.ATOM_REL_ALT, mediaType, href));
            }
        }
        return set;
    }

    private static Set<MediaType> getProducedTypesForGet(List<MethodMetadata> methods) {
        Set<MediaType> getResponses = new LinkedHashSet<MediaType>();
        if (methods != null) {
            for (MethodMetadata methodRecord : methods) {
                if (methodRecord.getHttpMethod().equals(HttpMethod.GET)) {
                    getResponses.addAll(methodRecord.getProduces());
                }
            }
        }
        return getResponses;
    }

    private Set<LinkType> generateSystemLinksSet() {
        Set<LinkType> systemLinksSet = new HashSet<LinkType>();
        if (types == null || types.length == 0) {
            for (LinkType type : LinkType.values()) {
                systemLinksSet.add(type);
            }
        } else {
            for (LinkType type : types) {
                systemLinksSet.add(type);
            }
        }
        return systemLinksSet;
    }

}
TOP

Related Classes of org.apache.wink.server.internal.utils.SystemLinksBuilderImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.