/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* 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.asakusafw.operator.util;
import java.util.Objects;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import com.asakusafw.operator.CompileEnvironment;
import com.asakusafw.operator.Constants;
/**
* Common helper methods about types.
*/
public final class TypeHelper {
private TypeHelper() {
return;
}
/**
* Returns whether the target type represents an input dataset.
* @param environment current environment
* @param type target type
* @return {@code true} if represents an input, otherwise {@code false}
* @throws IllegalArgumentException if some parameters were {@code null}
* @see Constants#TYPE_IN
*/
public static boolean isIn(CompileEnvironment environment, TypeMirror type) {
Objects.requireNonNull(environment, "environment must not be null"); //$NON-NLS-1$
Objects.requireNonNull(type, "type must not be null"); //$NON-NLS-1$
if (type.getKind() != TypeKind.DECLARED) {
return false;
}
DeclaredType expected = environment.findDeclaredType(Constants.TYPE_IN);
DeclaredType erasure = (DeclaredType) environment.getErasure(type);
return environment.getProcessingEnvironment().getTypeUtils().isSameType(expected, erasure);
}
/**
* Returns the type argument of {@code In} type.
* @param environment current environment
* @param type target {@code In} type
* @return the type argument, or {@code null} if target type is not {@code In} type
* @throws IllegalArgumentException if some parameters were {@code null}
* @see #isIn(CompileEnvironment, TypeMirror)
*/
public static TypeMirror getInType(CompileEnvironment environment, TypeMirror type) {
Objects.requireNonNull(environment, "environment must not be null"); //$NON-NLS-1$
Objects.requireNonNull(type, "type must not be null"); //$NON-NLS-1$
if (isIn(environment, type) == false) {
return null;
}
return getTypeArgument((DeclaredType) type, 0);
}
/**
* Returns the type argument of {@code Out} type.
* @param environment current environment
* @param type target {@code Out} type
* @return the type argument, or {@code null} if target type is not {@code Out} type
* @throws IllegalArgumentException if some parameters were {@code null}
* @see #isIn(CompileEnvironment, TypeMirror)
*/
public static TypeMirror getOutType(CompileEnvironment environment, TypeMirror type) {
Objects.requireNonNull(environment, "environment must not be null"); //$NON-NLS-1$
Objects.requireNonNull(type, "type must not be null"); //$NON-NLS-1$
if (isOut(environment, type) == false) {
return null;
}
return getTypeArgument((DeclaredType) type, 0);
}
private static TypeMirror getTypeArgument(DeclaredType type, int index) {
if (index >= type.getTypeArguments().size()) {
return null;
}
return type.getTypeArguments().get(index);
}
/**
* Returns whether the target type represents an output dataset.
* @param environment current environment
* @param type target type
* @return {@code true} if represents an output, otherwise {@code false}
* @throws IllegalArgumentException if some parameters were {@code null}
* @see Constants#TYPE_IN
*/
public static boolean isOut(CompileEnvironment environment, TypeMirror type) {
Objects.requireNonNull(environment, "environment must not be null"); //$NON-NLS-1$
Objects.requireNonNull(type, "type must not be null"); //$NON-NLS-1$
if (type.getKind() != TypeKind.DECLARED) {
return false;
}
DeclaredType expected = environment.findDeclaredType(Constants.TYPE_OUT);
DeclaredType erasure = (DeclaredType) environment.getErasure(type);
return environment.getProcessingEnvironment().getTypeUtils().isSameType(expected, erasure);
}
/**
* Returns whether the target type is an operator helper annotation.
* @param environment current environment
* @param type target type
* @return {@code true} if is an operator helper annotation, otherwise {@code false}
* @throws IllegalArgumentException if some parameters were {@code null}
* @see Constants#TYPE_ANNOTATION_HELPER
*/
public static boolean isOperatorHelper(CompileEnvironment environment, TypeMirror type) {
if (type.getKind() != TypeKind.DECLARED) {
return false;
}
TypeElement element = (TypeElement) ((DeclaredType) type).asElement();
if (element.getKind() != ElementKind.ANNOTATION_TYPE) {
return false;
}
DeclaredType operatorHelperType = environment.findDeclaredType(Constants.TYPE_ANNOTATION_HELPER);
for (AnnotationMirror metaAnnotation : element.getAnnotationMirrors()) {
Types types = environment.getProcessingEnvironment().getTypeUtils();
if (types.isSameType(operatorHelperType, metaAnnotation.getAnnotationType())) {
return true;
}
}
return false;
}
}