001: /**
002: * Copyright 2007 Jens Dietrich Licensed under the Apache License, Version 2.0 (the "License");
003: * you may not use this file except in compliance with the License.
004: * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
005: * Unless required by applicable law or agreed to in writing, software distributed under the
006: * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
007: * either express or implied. See the License for the specific language governing permissions
008: * and limitations under the License.
009: */package nz.org.take;
010:
011: /**
012: * Predicates based on Java properties as defined in the JavaBeans spec.
013: * @author <a href="http://www-ist.massey.ac.nz/JBDietrich/">Jens Dietrich</a>
014: */
015:
016: import java.lang.reflect.Method;
017: import java.lang.reflect.ParameterizedType;
018: import java.lang.reflect.Type;
019: import java.util.Arrays;
020:
021: public class PropertyPredicate extends AbstractPredicate {
022: private java.beans.PropertyDescriptor property = null;
023: private Class[] types = null;
024: private Class ownerType = null;
025: private boolean isOne2One = true; // false => One2Many
026:
027: public String getName() {
028: return property.getName();
029: }
030:
031: @Override
032: public int hashCode() {
033: final int PRIME = 31;
034: int result = 1;
035: result = PRIME * result + (isOne2One ? 1231 : 1237);
036: result = PRIME * result + (negated ? 1231 : 1237);
037: result = PRIME * result
038: + ((ownerType == null) ? 0 : ownerType.hashCode());
039: result = PRIME * result
040: + ((property == null) ? 0 : property.hashCode());
041: result = PRIME * result + Arrays.hashCode(types);
042: return result;
043: }
044:
045: @Override
046: public boolean equals(Object obj) {
047: if (this == obj)
048: return true;
049: if (obj == null)
050: return false;
051: if (getClass() != obj.getClass())
052: return false;
053: final PropertyPredicate other = (PropertyPredicate) obj;
054: if (isOne2One != other.isOne2One)
055: return false;
056: if (negated != other.negated)
057: return false;
058: if (ownerType == null) {
059: if (other.ownerType != null)
060: return false;
061: } else if (!ownerType.equals(other.ownerType))
062: return false;
063: if (property == null) {
064: if (other.property != null)
065: return false;
066: } else if (!property.equals(other.property))
067: return false;
068: if (!Arrays.equals(types, other.types))
069: return false;
070: return true;
071: }
072:
073: public Class[] getSlotTypes() {
074: if (types == null && property != null) {
075: Class clazz = property.getPropertyType();
076: // boolean properties are special !
077: if (clazz == Boolean.class || clazz == Boolean.TYPE) {
078: types = new Class[1];
079: types[0] = ownerType;
080: return types;
081: }
082: types = new Class[2];
083: types[0] = ownerType;
084:
085: if (java.util.Collection.class.isAssignableFrom(clazz)) {
086: isOne2One = false;
087: // check for generics
088: Method m = property.getReadMethod();
089: Type gtype = m.getGenericReturnType();
090: if (gtype instanceof ParameterizedType) {
091: ParameterizedType ptype = (ParameterizedType) gtype;
092: Type otype = ptype.getOwnerType();
093: Type rtype = ptype.getRawType();
094: Type[] atypes = ptype.getActualTypeArguments();
095: // TODO check whether this is really necessary
096: if (atypes.length == 0)
097: types[1] = Object.class;
098: types[1] = (Class) atypes[0];
099: } else
100: types[1] = Object.class;
101:
102: } else if (clazz.isArray()) {
103: types[1] = clazz.getComponentType();
104: isOne2One = false;
105: } else {
106: types[1] = clazz;
107: }
108: }
109: return types;
110: }
111:
112: public boolean isOne2One() {
113: return isOne2One;
114: }
115:
116: public void setOne2One(boolean isOne2One) {
117: this .isOne2One = isOne2One;
118: }
119:
120: public java.beans.PropertyDescriptor getProperty() {
121: return property;
122: }
123:
124: public void setProperty(java.beans.PropertyDescriptor property) {
125: this .property = property;
126: }
127:
128: public Class getOwnerType() {
129: return ownerType;
130: }
131:
132: public void setOwnerType(Class ownerType) {
133: this .ownerType = ownerType;
134: }
135:
136: public String toString() {
137: return (negated ? "!" : "") + property.getName();
138: }
139: }
|