/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * 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 com.hazelcast.query.impl.getters; import com.hazelcast.util.CollectionUtil; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; import static com.hazelcast.query.impl.getters.AbstractMultiValueGetter.validateModifier; public final class GetterFactory { private GetterFactory() { } public static Getter newFieldGetter(Object object, Getter parentGetter, Field field, String modifierSuffix) throws Exception { Class<?> fieldType = field.getType(); Class<?> returnType = null; if (isExtractingFromCollection(fieldType, modifierSuffix)) { validateModifier(modifierSuffix); Object currentObject = getCurrentObject(object, parentGetter); if (currentObject == null) { return NullGetter.NULL_GETTER; } if (currentObject instanceof MultiResult) { MultiResult multiResult = (MultiResult) currentObject; returnType = extractTypeFromMultiResult(field, multiResult); } else { Collection collection = (Collection) field.get(currentObject); returnType = getCollectionType(collection); } if (returnType == null) { return NullGetter.NULL_GETTER; } } else if (isExtractingFromArray(fieldType, modifierSuffix)) { validateModifier(modifierSuffix); Object currentObject = getCurrentObject(object, parentGetter); if (currentObject == null) { return NullGetter.NULL_GETTER; } } return new FieldGetter(parentGetter, field, modifierSuffix, returnType); } private static Class<?> extractTypeFromMultiResult(Field field, MultiResult multiResult) throws Exception { Class<?> returnType = null; for (Object o : multiResult.getResults()) { if (o == null) { continue; } Collection collection = (Collection) field.get(o); returnType = getCollectionType(collection); if (returnType != null) { break; } } return returnType; } public static Getter newMethodGetter(Object object, Getter parentGetter, Method method, String modifierSuffix) throws Exception { Class<?> methodReturnType = method.getReturnType(); Class<?> returnType = null; if (isExtractingFromCollection(methodReturnType, modifierSuffix)) { validateModifier(modifierSuffix); Object currentObject = getCurrentObject(object, parentGetter); if (currentObject == null) { return NullGetter.NULL_GETTER; } if (currentObject instanceof MultiResult) { MultiResult multiResult = (MultiResult) currentObject; returnType = extractTypeFromMultiResult(method, multiResult); } else { Collection collection = (Collection) method.invoke(currentObject); returnType = getCollectionType(collection); } if (returnType == null) { return NullGetter.NULL_GETTER; } } else if (isExtractingFromArray(methodReturnType, modifierSuffix)) { validateModifier(modifierSuffix); Object currentObject = getCurrentObject(object, parentGetter); if (currentObject == null) { return NullGetter.NULL_GETTER; } } return new MethodGetter(parentGetter, method, modifierSuffix, returnType); } private static Class<?> extractTypeFromMultiResult(Method method, MultiResult multiResult) throws Exception { Class<?> returnType = null; for (Object o : multiResult.getResults()) { if (o == null) { continue; } Collection collection = (Collection) method.invoke(o); returnType = getCollectionType(collection); if (returnType != null) { break; } } return returnType; } public static Getter newThisGetter(Getter parent, Object object) { return new ThisGetter(parent, object); } private static Class<?> getCollectionType(Collection collection) throws Exception { if (collection == null || collection.isEmpty()) { return null; } Object targetObject = CollectionUtil.getItemAtPositionOrNull(collection, 0); if (targetObject == null) { for (Object object : collection) { if (object != null) { return object.getClass(); } } return null; } return targetObject.getClass(); } private static boolean isExtractingFromCollection(Class<?> type, String modifierSuffix) { return modifierSuffix != null && Collection.class.isAssignableFrom(type); } private static boolean isExtractingFromArray(Class<?> type, String modifierSuffix) { return modifierSuffix != null && type.isArray(); } private static Object getCurrentObject(Object obj, Getter parent) throws Exception { return parent == null ? obj : parent.getValue(obj); } }