All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wink.server.internal.handlers.SearchResult 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.handlers;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.UriInfo;

import org.apache.wink.common.internal.MultivaluedMapImpl;
import org.apache.wink.common.internal.utils.UriHelper;
import org.apache.wink.server.internal.registry.MethodRecord;
import org.apache.wink.server.internal.registry.ResourceInstance;
import org.apache.wink.server.internal.registry.SubResourceLocatorRecord;
import org.apache.wink.server.internal.registry.SubResourceMethodRecord;

/**
 * Stores the result of searching for a resource method to dispatch a request to
 */
public class SearchResult {

    private boolean                 found;
    private WebApplicationException error;
    private ResourceInstance        resource;
    private MethodRecord            method;
    private Object[]                invocationParameters;
    private AccumulatedData         data;
    private UriInfo                 uriInfo;

    public static class AccumulatedData implements Cloneable {
        private UriInfo                                   uriInfo;
        private MultivaluedMap            matchedVariables;
        private MultivaluedMap> matchedVariablesPathSegments;
        private LinkedList>             matchedURIs;
        private LinkedList              matchedResources;

        public AccumulatedData(UriInfo uriInfo) {
            this.uriInfo = uriInfo;
        }

        @Override
        @SuppressWarnings("unchecked")
        public AccumulatedData clone() {
            AccumulatedData clone;
            try {
                clone = (AccumulatedData)super.clone();
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
            clone.matchedVariables = MultivaluedMapImpl.clone(getMatchedVariables());
            clone.matchedVariablesPathSegments =
                MultivaluedMapImpl.clone(getMatchedVariablesPathSegments());
            clone.matchedURIs = (LinkedList>)getMatchedURIs().clone();
            clone.matchedResources = (LinkedList)getMatchedResources().clone();
            return clone;
        }

        public void setMatchedVariables(MultivaluedMap matchedVariables) {
            this.matchedVariables = matchedVariables;
        }

        public void setMatchedURIs(LinkedList> matchedURIs) {
            this.matchedURIs = matchedURIs;
        }

        public void setMatchedResources(LinkedList matchedResources) {
            this.matchedResources = matchedResources;
        }

        public MultivaluedMap getMatchedVariables() {
            if (matchedVariables == null) {
                matchedVariables = new MultivaluedMapImpl();
            }
            return matchedVariables;
        }

        public MultivaluedMap> getMatchedVariablesPathSegments() {
            if (matchedVariablesPathSegments == null) {
                matchedVariablesPathSegments = new MultivaluedMapImpl>();
            }
            return matchedVariablesPathSegments;
        }

        public LinkedList getMatchedResources() {
            if (matchedResources == null) {
                matchedResources = new LinkedList();
            }
            return matchedResources;
        }

        public LinkedList> getMatchedURIs() {
            if (matchedURIs == null) {
                matchedURIs = new LinkedList>();
            }
            return matchedURIs;
        }

        /**
         * Used for providing the info for the {@link UriInfo#getMatchedURIs()}
         * method.
         * 
         * @param uri the uri that was used for the matching is stripped from
         *            any matrix parameters
         * @return the number of segments of the input uri
         */
        public int addMatchedURI(String uri) {
            // get all the segments of the original request (which include the
            // matrix parameters)
            List segments = uriInfo.getPathSegments(false);

            // count the number of segments in input uri
            int count = uri.equals("") ? 0 : UriHelper.parsePath(uri).size(); //$NON-NLS-1$

            // get the offset of the provided uri from the complete request path
            int offset = calculateUriOffset();

            // add the uri segments (including any matrix parameters) by
            // obtaining a sub list from the the complete request segments
            addMatchedURI(segments, offset, count);
            return count;
        }

        /**
         * Used to calculate the number of URI segments already matched.
         * 
         * @return the offset past the URI segments already matched
         */
        public int calculateUriOffset() {
            int offset = 0;
            if (getMatchedURIs().size() > 0) {
                // the first uri in the "matched uri's" list always reflects all
                // the path segments
                // that were matched until now, from the beginning of the
                // complete request uri
                List firstMatchedUri = getMatchedURIs().getFirst();
                offset = firstMatchedUri.size();
                // we need to skip all empty string as path segments that were
                // added
                // because of matches to @Path("") and @Path("/"), so decrease
                // the
                // offset by the number of empty segments
                for (PathSegment segment : firstMatchedUri) {
                    if (segment.getPath().equals("")) { //$NON-NLS-1$
                        --offset;
                    }
                }
            }
            return offset;
        }

        private void addMatchedURI(List segments, int offset, int count) {
            // obtain the sub list of uri segments from the the complete request
            // segments
            int toIndex = offset + count;
            List subListSegments = segments.subList(offset, toIndex);
            if (subListSegments.isEmpty()) {
                // the sublist may be empty if the count is 0. this can happen
                // if the given uri was an empty string (which itself can happen
                // if the resource/sub-resource are annotated with @Path("") or
                // @Path("/").
                subListSegments = UriHelper.parsePath(""); //$NON-NLS-1$
            }

            LinkedList> matchedURIs = getMatchedURIs();
            if (matchedURIs.size() == 0) {
                // if it's the first uri, simply add it
                matchedURIs.add(subListSegments);
                return;
            }

            // need to concatenate the sub list of segments to the first uri in
            // the list of matched uri's
            List currentMatchedUri = matchedURIs.getFirst();
            List newMatchedUri =
                new ArrayList(currentMatchedUri.size() + subListSegments.size());
            newMatchedUri.addAll(currentMatchedUri);
            newMatchedUri.addAll(subListSegments);
            matchedURIs.addFirst(newMatchedUri);
        }

        public ResourceInstance getResource() {
            return matchedResources.getFirst();
        }

    }

    public enum MethodType {
        ResourceMethod, SubResourceMethod, SubResourceLocator;
    }

    @Override
    public String toString() {
        return String.format("Found: %s, Resource: %s, Method: %s, Error: %s", //$NON-NLS-1$
                             found,
                             resource,
                             method,
                             error);
    }

    public SearchResult(ResourceInstance resource, UriInfo uriInfo) {
        this(false);
        this.uriInfo = uriInfo;
        getData().getMatchedResources().addFirst(resource);
    }

    public SearchResult(WebApplicationException error) {
        this(false);
        this.error = error;
    }

    private SearchResult(boolean found) {
        this.found = found;
        this.error = null;
        this.uriInfo = null;
    }

    public ResourceInstance getResource() {
        if (getData().getMatchedResources().isEmpty()) {
            return null;
        }
        return getData().getMatchedResources().getFirst();
    }

    public MethodRecord getMethod() {
        return method;
    }

    public SearchResult setMethod(MethodRecord method) {
        this.method = method;
        return this;
    }

    public MethodType getMethodType() {
        if (method instanceof SubResourceMethodRecord) {
            return MethodType.SubResourceMethod;
        }
        if (method instanceof SubResourceLocatorRecord) {
            return MethodType.SubResourceLocator;
        }
        return MethodType.ResourceMethod;
    }

    public Object[] getInvocationParameters() {
        return invocationParameters;
    }

    public void setInvocationParameters(Object[] invocationParameters) {
        this.invocationParameters = invocationParameters;
    }

    public WebApplicationException getError() {
        return error;
    }

    public SearchResult setError(WebApplicationException error) {
        this.error = error;
        if (error != null) {
            this.found = false;
        }
        return this;
    }

    public boolean isError() {
        return error != null;
    }

    public SearchResult setFound(boolean found) {
        this.found = found;
        this.error = null;
        return this;
    }

    public boolean isFound() {
        return this.found;
    }

    public AccumulatedData getData() {
        if (data == null) {
            data = new AccumulatedData(uriInfo);
        }
        return data;
    }

    public void setData(AccumulatedData data) {
        this.data = data;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy