001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.actuate.endpoint.web;
018
019import java.util.Collection;
020import java.util.Collections;
021import java.util.regex.Pattern;
022
023import org.springframework.util.CollectionUtils;
024import org.springframework.util.StringUtils;
025
026/**
027 * A predicate for a request to an operation on a web endpoint.
028 *
029 * @author Andy Wilkinson
030 * @since 2.0.0
031 */
032public final class WebOperationRequestPredicate {
033
034        private static final Pattern PATH_VAR_PATTERN = Pattern.compile("\\{.*?}");
035
036        private final String path;
037
038        private final String canonicalPath;
039
040        private final WebEndpointHttpMethod httpMethod;
041
042        private final Collection<String> consumes;
043
044        private final Collection<String> produces;
045
046        /**
047         * Creates a new {@code OperationRequestPredicate}.
048         * @param path the path for the operation
049         * @param httpMethod the HTTP method that the operation supports
050         * @param produces the media types that the operation produces
051         * @param consumes the media types that the operation consumes
052         */
053        public WebOperationRequestPredicate(String path, WebEndpointHttpMethod httpMethod,
054                        Collection<String> consumes, Collection<String> produces) {
055                this.path = path;
056                this.canonicalPath = PATH_VAR_PATTERN.matcher(path).replaceAll("{*}");
057                this.httpMethod = httpMethod;
058                this.consumes = consumes;
059                this.produces = produces;
060        }
061
062        /**
063         * Returns the path for the operation.
064         * @return the path
065         */
066        public String getPath() {
067                return this.path;
068        }
069
070        /**
071         * Returns the HTTP method for the operation.
072         * @return the HTTP method
073         */
074        public WebEndpointHttpMethod getHttpMethod() {
075                return this.httpMethod;
076        }
077
078        /**
079         * Returns the media types that the operation consumes.
080         * @return the consumed media types
081         */
082        public Collection<String> getConsumes() {
083                return Collections.unmodifiableCollection(this.consumes);
084        }
085
086        /**
087         * Returns the media types that the operation produces.
088         * @return the produced media types
089         */
090        public Collection<String> getProduces() {
091                return Collections.unmodifiableCollection(this.produces);
092        }
093
094        @Override
095        public boolean equals(Object obj) {
096                if (this == obj) {
097                        return true;
098                }
099                if (obj == null || getClass() != obj.getClass()) {
100                        return false;
101                }
102                WebOperationRequestPredicate other = (WebOperationRequestPredicate) obj;
103                boolean result = true;
104                result = result && this.consumes.equals(other.consumes);
105                result = result && this.httpMethod == other.httpMethod;
106                result = result && this.canonicalPath.equals(other.canonicalPath);
107                result = result && this.produces.equals(other.produces);
108                return result;
109        }
110
111        @Override
112        public int hashCode() {
113                final int prime = 31;
114                int result = 1;
115                result = prime * result + this.consumes.hashCode();
116                result = prime * result + this.httpMethod.hashCode();
117                result = prime * result + this.canonicalPath.hashCode();
118                result = prime * result + this.produces.hashCode();
119                return result;
120        }
121
122        @Override
123        public String toString() {
124                StringBuilder result = new StringBuilder(
125                                this.httpMethod + " to path '" + this.path + "'");
126                if (!CollectionUtils.isEmpty(this.consumes)) {
127                        result.append(" consumes: "
128                                        + StringUtils.collectionToCommaDelimitedString(this.consumes));
129                }
130                if (!CollectionUtils.isEmpty(this.produces)) {
131                        result.append(" produces: "
132                                        + StringUtils.collectionToCommaDelimitedString(this.produces));
133                }
134                return result.toString();
135        }
136
137}