1 19 20 package org.apache.cayenne.query; 21 22 import java.util.Arrays ; 23 import java.util.Collections ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.Map ; 27 28 import org.apache.cayenne.CayenneRuntimeException; 29 import org.apache.cayenne.Persistent; 30 import org.apache.cayenne.map.EntityResolver; 31 import org.apache.cayenne.util.Util; 32 import org.apache.commons.lang.StringUtils; 33 import org.apache.commons.lang.builder.EqualsBuilder; 34 import org.apache.commons.lang.builder.HashCodeBuilder; 35 36 43 public class NamedQuery extends IndirectQuery { 44 45 protected Map parameters; 46 47 protected boolean forceNoCache; 48 49 protected BaseQueryMetadata overrideMetadata; 50 51 transient int hashCode; 53 54 public NamedQuery(String name) { 55 this(name, null); 56 } 57 58 public NamedQuery(String name, Map parameters) { 59 this.name = name; 60 61 if (parameters != null && !parameters.isEmpty()) { 63 this.parameters = new HashMap (parameters); 64 } 65 } 66 67 71 public NamedQuery(String name, String [] keys, Object [] values) { 72 this.name = name; 73 this.parameters = Util.toMap(keys, values); 74 } 75 76 public QueryMetadata getMetaData(EntityResolver resolver) { 77 78 QueryMetadata base = overrideMetadata != null ? overrideMetadata : super 79 .getMetaData(resolver); 80 81 QueryMetadataWrapper wrapper = new QueryMetadataWrapper(base); 82 83 if (forceNoCache) { 85 String policy = base.getCachePolicy(); 86 87 if (QueryMetadata.LOCAL_CACHE.equals(policy)) { 88 wrapper.override( 89 QueryMetadata.CACHE_POLICY_PROPERTY, 90 QueryMetadata.LOCAL_CACHE_REFRESH); 91 } 92 else if (QueryMetadata.SHARED_CACHE.equals(policy)) { 93 wrapper.override( 94 QueryMetadata.CACHE_POLICY_PROPERTY, 95 QueryMetadata.SHARED_CACHE_REFRESH); 96 } 97 } 98 99 if (parameters != null 101 && !parameters.isEmpty() 102 && replacementQuery instanceof NamedQuery 103 && base.getCacheKey() != null) { 104 105 108 StringBuffer buffer = new StringBuffer (name); 109 110 if (parameters != null && !parameters.isEmpty()) { 111 buffer.append(parameters.hashCode()); 112 } 113 114 wrapper.override(QueryMetadataWrapper.CACHE_KEY_PROPERTY, buffer.toString()); 115 } 116 117 return wrapper; 118 } 119 120 protected Query createReplacementQuery(EntityResolver resolver) { 121 Query query = resolveQuery(resolver); 122 123 if (query instanceof ParameterizedQuery) { 124 query = ((ParameterizedQuery) query).createQuery(normalizedParameters()); 125 } 126 127 return query; 128 } 129 130 135 Map normalizedParameters() { 136 if (parameters == null || parameters.isEmpty()) { 137 return Collections.EMPTY_MAP; 138 } 139 140 Map substitutes = new HashMap (parameters); 141 142 Iterator it = parameters.entrySet().iterator(); 143 while (it.hasNext()) { 144 Map.Entry entry = (Map.Entry ) it.next(); 145 146 Object value = entry.getValue(); 147 148 if (value instanceof Persistent) { 149 value = ((Persistent) value).getObjectId(); 150 } 151 152 substitutes.put(entry.getKey(), value); 153 } 154 155 return substitutes; 156 } 157 158 162 protected Query resolveQuery(EntityResolver resolver) { 163 Query query = resolver.lookupQuery(getName()); 164 165 if (query == null) { 166 throw new CayenneRuntimeException("Can't find named query for name '" 167 + getName() 168 + "'"); 169 } 170 171 if (query == this) { 172 throw new CayenneRuntimeException("Named query resolves to self: '" 173 + getName() 174 + "'"); 175 } 176 177 return query; 178 } 179 180 183 public String toString() { 184 return StringUtils.substringAfterLast(getClass().getName(), ".") 185 + ":" 186 + getName(); 187 } 188 189 193 public void initMetadata(QueryMetadata metadata) { 194 if (metadata != null) { 195 this.overrideMetadata = new BaseQueryMetadata(); 196 this.overrideMetadata.copyFromInfo(metadata); 197 } 198 else { 199 this.overrideMetadata = null; 200 } 201 } 202 203 207 public boolean equals(Object object) { 208 if (this == object) { 209 return true; 210 } 211 212 if (!(object instanceof NamedQuery)) { 213 return false; 214 } 215 216 NamedQuery query = (NamedQuery) object; 217 218 if (!Util.nullSafeEquals(name, query.getName())) { 219 return false; 220 } 221 222 if (query.parameters == null && parameters == null) { 223 return true; 224 } 225 226 if (query.parameters == null || parameters == null) { 227 return false; 228 } 229 230 if (query.parameters.size() != parameters.size()) { 231 return false; 232 } 233 234 EqualsBuilder builder = new EqualsBuilder(); 235 Iterator entries = parameters.entrySet().iterator(); 236 while (entries.hasNext()) { 237 Map.Entry entry = (Map.Entry ) entries.next(); 238 Object entryKey = entry.getKey(); 239 Object entryValue = entry.getValue(); 240 241 if (entryValue == null) { 242 if (query.parameters.get(entryKey) != null 243 || !query.parameters.containsKey(entryKey)) { 244 return false; 245 } 246 } 247 else { 248 builder.append(entryValue, query.parameters.get(entryKey)); 250 if (!builder.isEquals()) { 251 return false; 252 } 253 } 254 } 255 256 return true; 257 } 258 259 262 public int hashCode() { 263 264 if (this.hashCode == 0) { 265 266 HashCodeBuilder builder = new HashCodeBuilder(13, 17); 267 268 if (name != null) { 269 builder.append(name.hashCode()); 270 } 271 272 if (parameters != null) { 273 Object [] keys = parameters.keySet().toArray(); 274 Arrays.sort(keys); 275 276 for (int i = 0; i < keys.length; i++) { 277 builder.append(keys[i]).append(parameters.get(keys[i])); 280 } 281 282 } 283 284 this.hashCode = builder.toHashCode(); 285 assert hashCode != 0 : "Generated zero hashCode"; 286 } 287 288 return hashCode; 289 } 290 291 public boolean isForceNoCache() { 292 return forceNoCache; 293 } 294 295 public void setForceNoCache(boolean forcingNoCache) { 296 this.forceNoCache = forcingNoCache; 297 } 298 } 299 | Popular Tags |