001/*
002 * Copyright 2002-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 *      https://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.cache.interceptor;
018
019import java.util.Collections;
020import java.util.LinkedHashSet;
021import java.util.Set;
022
023import org.springframework.lang.Nullable;
024import org.springframework.util.Assert;
025
026/**
027 * Base class for cache operations.
028 *
029 * @author Costin Leau
030 * @author Stephane Nicoll
031 * @author Marcin Kamionowski
032 * @since 3.1
033 */
034public abstract class CacheOperation implements BasicOperation {
035
036        private final String name;
037
038        private final Set<String> cacheNames;
039
040        private final String key;
041
042        private final String keyGenerator;
043
044        private final String cacheManager;
045
046        private final String cacheResolver;
047
048        private final String condition;
049
050        private final String toString;
051
052
053        /**
054         * Create a new {@link CacheOperation} instance from the given builder.
055         * @since 4.3
056         */
057        protected CacheOperation(Builder b) {
058                this.name = b.name;
059                this.cacheNames = b.cacheNames;
060                this.key = b.key;
061                this.keyGenerator = b.keyGenerator;
062                this.cacheManager = b.cacheManager;
063                this.cacheResolver = b.cacheResolver;
064                this.condition = b.condition;
065                this.toString = b.getOperationDescription().toString();
066        }
067
068
069        public String getName() {
070                return this.name;
071        }
072
073        @Override
074        public Set<String> getCacheNames() {
075                return this.cacheNames;
076        }
077
078        public String getKey() {
079                return this.key;
080        }
081
082        public String getKeyGenerator() {
083                return this.keyGenerator;
084        }
085
086        public String getCacheManager() {
087                return this.cacheManager;
088        }
089
090        public String getCacheResolver() {
091                return this.cacheResolver;
092        }
093
094        public String getCondition() {
095                return this.condition;
096        }
097
098
099        /**
100         * This implementation compares the {@code toString()} results.
101         * @see #toString()
102         */
103        @Override
104        public boolean equals(@Nullable Object other) {
105                return (other instanceof CacheOperation && toString().equals(other.toString()));
106        }
107
108        /**
109         * This implementation returns {@code toString()}'s hash code.
110         * @see #toString()
111         */
112        @Override
113        public int hashCode() {
114                return toString().hashCode();
115        }
116
117        /**
118         * Return an identifying description for this cache operation.
119         * <p>Returned value is produced by calling {@link Builder#getOperationDescription()}
120         * during object construction. This method is used in {@link #hashCode} and
121         * {@link #equals}.
122         * @see Builder#getOperationDescription()
123         */
124        @Override
125        public final String toString() {
126                return this.toString;
127        }
128
129
130        /**
131         * Base class for builders that can be used to create a {@link CacheOperation}.
132         * @since 4.3
133         */
134        public abstract static class Builder {
135
136                private String name = "";
137
138                private Set<String> cacheNames = Collections.emptySet();
139
140                private String key = "";
141
142                private String keyGenerator = "";
143
144                private String cacheManager = "";
145
146                private String cacheResolver = "";
147
148                private String condition = "";
149
150                public void setName(String name) {
151                        Assert.hasText(name, "Name must not be empty");
152                        this.name = name;
153                }
154
155                public void setCacheName(String cacheName) {
156                        Assert.hasText(cacheName, "Cache name must not be empty");
157                        this.cacheNames = Collections.singleton(cacheName);
158                }
159
160                public void setCacheNames(String... cacheNames) {
161                        this.cacheNames = new LinkedHashSet<>(cacheNames.length);
162                        for (String cacheName : cacheNames) {
163                                Assert.hasText(cacheName, "Cache name must be non-empty if specified");
164                                this.cacheNames.add(cacheName);
165                        }
166                }
167
168                public Set<String> getCacheNames() {
169                        return this.cacheNames;
170                }
171
172                public void setKey(String key) {
173                        Assert.notNull(key, "Key must not be null");
174                        this.key = key;
175                }
176
177                public String getKey() {
178                        return this.key;
179                }
180
181                public String getKeyGenerator() {
182                        return this.keyGenerator;
183                }
184
185                public String getCacheManager() {
186                        return this.cacheManager;
187                }
188
189                public String getCacheResolver() {
190                        return this.cacheResolver;
191                }
192
193                public void setKeyGenerator(String keyGenerator) {
194                        Assert.notNull(keyGenerator, "KeyGenerator name must not be null");
195                        this.keyGenerator = keyGenerator;
196                }
197
198                public void setCacheManager(String cacheManager) {
199                        Assert.notNull(cacheManager, "CacheManager name must not be null");
200                        this.cacheManager = cacheManager;
201                }
202
203                public void setCacheResolver(String cacheResolver) {
204                        Assert.notNull(cacheResolver, "CacheResolver name must not be null");
205                        this.cacheResolver = cacheResolver;
206                }
207
208                public void setCondition(String condition) {
209                        Assert.notNull(condition, "Condition must not be null");
210                        this.condition = condition;
211                }
212
213                /**
214                 * Return an identifying description for this caching operation.
215                 * <p>Available to subclasses, for inclusion in their {@code toString()} result.
216                 */
217                protected StringBuilder getOperationDescription() {
218                        StringBuilder result = new StringBuilder(getClass().getSimpleName());
219                        result.append("[").append(this.name);
220                        result.append("] caches=").append(this.cacheNames);
221                        result.append(" | key='").append(this.key);
222                        result.append("' | keyGenerator='").append(this.keyGenerator);
223                        result.append("' | cacheManager='").append(this.cacheManager);
224                        result.append("' | cacheResolver='").append(this.cacheResolver);
225                        result.append("' | condition='").append(this.condition).append("'");
226                        return result;
227                }
228
229                public abstract CacheOperation build();
230        }
231
232}