/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.utils.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* A criteria that matches a property based on its type
*
* @see PropertyCriteria
*/
public class TypedPropertyCriteria implements PropertyCriteria {
/**
* <p> Different options can be used to match a specific property based on its type. Regardless of the option
* chosen, if the property type equals the <code>propertyClass</code> it will be selected. <p/> <ul> <li>SUB_TYPE:
* Also consider properties where its type is a subtype of <code>propertyClass</code>. .</li> <li>SUPER_TYPE: Also
* consider properties where its type is a superclass or superinterface of <code>propertyClass</code>. .</li> </ul>
* </p>
*/
public static enum MatchOption {
SUB_TYPE, SUPER_TYPE, ALL
}
private final Class<?> propertyClass;
private final MatchOption matchOption;
public TypedPropertyCriteria(Class<?> propertyClass) {
this(propertyClass, null);
}
public TypedPropertyCriteria(Class<?> propertyClass, MatchOption matchOption) {
if (propertyClass == null) {
throw new IllegalArgumentException("Property class can not be null.");
}
this.propertyClass = propertyClass;
this.matchOption = matchOption;
}
public boolean fieldMatches(Field f) {
return match(f.getType());
}
public boolean methodMatches(Method m) {
return match(m.getReturnType());
}
private boolean match(Class<?> type) {
if (propertyClass.equals(type)) {
return true;
} else {
boolean matchSubType = propertyClass.isAssignableFrom(type);
if (MatchOption.SUB_TYPE == this.matchOption) {
return matchSubType;
}
boolean matchSuperType = type.isAssignableFrom(propertyClass);
if (MatchOption.SUPER_TYPE == this.matchOption) {
return matchSuperType;
}
if (MatchOption.ALL == this.matchOption) {
return matchSubType || matchSuperType;
}
}
return false;
}
}