org.apache.wink.server.internal.utils.SystemLinksBuilderImpl Maven / Gradle / Ivy
/*******************************************************************************
* 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.handlers.MessageContext;
import org.apache.wink.server.internal.handlers.FindRootResourceHandler;
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 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 build(List out) {
Set set = new HashSet();
// 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 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();
}
out.addAll(set);
return out;
}
private Set build(Set set, UriBuilder selfUriBuilder, ResourceRecord record) {
List methods = null;
if (subResourcePath != null && subResourcePath.length() > 0) {
// 1) find all the sub-resources that match the sub-resource path
List subResources =
record.getMatchingSubResourceMethods(subResourcePath);
methods = new LinkedList();
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 build(Set set,
UriBuilder selfUriBuilder,
List 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 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 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 getProducedTypesForGet(List methods) {
Set getResponses = new LinkedHashSet();
if (methods != null) {
for (MethodMetadata methodRecord : methods) {
if (methodRecord.getHttpMethod().equals(HttpMethod.GET)) {
getResponses.addAll(methodRecord.getProduces());
}
}
}
return getResponses;
}
private Set generateSystemLinksSet() {
Set systemLinksSet = new HashSet();
if (types == null || types.length == 0) {
for (LinkType type : LinkType.values()) {
systemLinksSet.add(type);
}
} else {
for (LinkType type : types) {
systemLinksSet.add(type);
}
}
return systemLinksSet;
}
}