View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.web.servlet.mvc.condition;
18  
19  import java.util.Collection;
20  import java.util.Collections;
21  import javax.servlet.http.HttpServletRequest;
22  
23  /**
24   * A holder for a {@link RequestCondition} useful when the type of the request
25   * condition is not known ahead of time, e.g. custom condition. Since this
26   * class is also an implementation of {@code RequestCondition}, effectively it
27   * decorates the held request condition and allows it to be combined and compared
28   * with other request conditions in a type and null safe way.
29   *
30   * <p>When two {@code RequestConditionHolder} instances are combined or compared
31   * with each other, it is expected the conditions they hold are of the same type.
32   * If they are not, a {@link ClassCastException} is raised.
33   *
34   * @author Rossen Stoyanchev
35   * @since 3.1
36   */
37  public final class RequestConditionHolder extends AbstractRequestCondition<RequestConditionHolder> {
38  
39  	private final RequestCondition<Object> condition;
40  
41  
42  	/**
43  	 * Create a new holder to wrap the given request condition.
44  	 * @param requestCondition the condition to hold, may be {@code null}
45  	 */
46  	@SuppressWarnings("unchecked")
47  	public RequestConditionHolder(RequestCondition<?> requestCondition) {
48  		this.condition = (RequestCondition<Object>) requestCondition;
49  	}
50  
51  
52  	/**
53  	 * Return the held request condition, or {@code null} if not holding one.
54  	 */
55  	public RequestCondition<?> getCondition() {
56  		return this.condition;
57  	}
58  
59  	@Override
60  	protected Collection<?> getContent() {
61  		return (this.condition != null ? Collections.singleton(this.condition) : Collections.emptyList());
62  	}
63  
64  	@Override
65  	protected String getToStringInfix() {
66  		return " ";
67  	}
68  
69  	/**
70  	 * Combine the request conditions held by the two RequestConditionHolder
71  	 * instances after making sure the conditions are of the same type.
72  	 * Or if one holder is empty, the other holder is returned.
73  	 */
74  	@Override
75  	public RequestConditionHolder combine(RequestConditionHolder other) {
76  		if (this.condition == null && other.condition == null) {
77  			return this;
78  		}
79  		else if (this.condition == null) {
80  			return other;
81  		}
82  		else if (other.condition == null) {
83  			return this;
84  		}
85  		else {
86  			assertEqualConditionTypes(other);
87  			RequestCondition<?> combined = (RequestCondition<?>) this.condition.combine(other.condition);
88  			return new RequestConditionHolder(combined);
89  		}
90  	}
91  
92  	/**
93  	 * Ensure the held request conditions are of the same type.
94  	 */
95  	private void assertEqualConditionTypes(RequestConditionHolder other) {
96  		Class<?> clazz = this.condition.getClass();
97  		Class<?> otherClazz = other.condition.getClass();
98  		if (!clazz.equals(otherClazz)) {
99  			throw new ClassCastException("Incompatible request conditions: " + clazz + " and " + otherClazz);
100 		}
101 	}
102 
103 	/**
104 	 * Get the matching condition for the held request condition wrap it in a
105 	 * new RequestConditionHolder instance. Or otherwise if this is an empty
106 	 * holder, return the same holder instance.
107 	 */
108 	@Override
109 	public RequestConditionHolder getMatchingCondition(HttpServletRequest request) {
110 		if (this.condition == null) {
111 			return this;
112 		}
113 		RequestCondition<?> match = (RequestCondition<?>) this.condition.getMatchingCondition(request);
114 		return (match != null ? new RequestConditionHolder(match) : null);
115 	}
116 
117 	/**
118 	 * Compare the request conditions held by the two RequestConditionHolder
119 	 * instances after making sure the conditions are of the same type.
120 	 * Or if one holder is empty, the other holder is preferred.
121 	 */
122 	@Override
123 	public int compareTo(RequestConditionHolder other, HttpServletRequest request) {
124 		if (this.condition == null && other.condition == null) {
125 			return 0;
126 		}
127 		else if (this.condition == null) {
128 			return 1;
129 		}
130 		else if (other.condition == null) {
131 			return -1;
132 		}
133 		else {
134 			assertEqualConditionTypes(other);
135 			return this.condition.compareTo(other.condition, request);
136 		}
137 	}
138 
139 }