/*
* Copyright 2008-2010 the T2 Project ant the Others.
*
* 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.t2framework.confeito.internal;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import org.t2framework.confeito.Constants;
import org.t2framework.confeito.util.Logger;
import org.t2framework.confeito.util.StringUtil;
import org.t2framework.confeito.util.Reflections.MethodUtil;
/**
* <#if locale="en">
* <p>
* Internal action info class.
*
* </p>
* <#else>
* <p>
*
* </p>
* </#if>
*
* @author shot
*
*/
public class ActionInfo {
/**
* The logger for this class.
*/
protected static Logger logger = Logger.getLogger(ActionInfo.class);
/**
* The target {@link MethodDesc}.
*/
public Method methodDesc;
/**
* The target method name.
*/
public String methodName;
/**
* Efficient annotation counts.
*/
public int annotationCounts;
/**
* The template path
*/
public String templatePath;
/**
* Default action or not.
*/
public boolean defaultAction;
protected Set<Class<? extends Annotation>> actionAnnotationSet;
public ActionInfo(Method methodDesc,
Set<Class<? extends Annotation>> actionAnnotationSet) {
this(methodDesc.getName(), methodDesc, actionAnnotationSet, false);
}
public ActionInfo(String methodName, Method methodDesc,
Set<Class<? extends Annotation>> actionAnnotationSet) {
this(methodName, methodDesc, actionAnnotationSet, false);
}
public ActionInfo(String methodName, Method methodDesc,
Set<Class<? extends Annotation>> actionAnnotationSet,
boolean defaultAction) {
this.methodDesc = methodDesc;
this.methodName = methodName;
this.actionAnnotationSet = actionAnnotationSet;
this.defaultAction = defaultAction;
init(methodDesc);
}
public ActionInfo(Method methodDesc,
Set<Class<? extends Annotation>> actionAnnotationSet,
boolean defaultAction) {
this(methodDesc.getName(), methodDesc, actionAnnotationSet,
defaultAction);
}
/**
*
* <#if locale="en">
* <p>
* Initialize this {@link ActionInfo}.
*
* With given {@link MethodDesc}, find template path from T2 framework
* annotations which is for action method, and counts how many annotations
* exist.
* </p>
* <#else>
* <p>
* </p>
* </#if>
*
* @param methodDesc
*/
protected void init(Method methodDesc) {
int count = 0;
List<String> paths = new ArrayList<String>();
for (Class<? extends Annotation> c : actionAnnotationSet) {
Annotation annotation = methodDesc.getAnnotation(c);
if (annotation == null) {
continue;
}
Method annotationMethod = getTemplatePathReturnMethod(c);
if (isApplicableAnnotationMethod(annotationMethod)) {
try {
String templatePath = (String) annotationMethod.invoke(
annotation, Constants.EMPTY_ARRAY);
paths.add(templatePath);
} catch (Throwable ignore) {
logger.debug(ignore.getMessage());
}
}
count++;
}
Collections.sort(paths, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
final String pageTemplatePath2 = s2.replaceAll("\\{.*\\}", "");
final String pageTemplatePath1 = s1.replaceAll("\\{.*\\}", "");
return pageTemplatePath2.length() - pageTemplatePath1.length();
}
});
if (paths.isEmpty()) {
this.templatePath = this.methodName;
} else {
String path = paths.get(0);
this.templatePath = (StringUtil.isEmpty(path) == false) ? path
: this.methodName;
}
this.annotationCounts = count;
}
/**
*
* <#if locale="en">
* <p>
* True if the given annotation method is applicable for resolving template
* path.
* </p>
* <#else>
* <p>
* </p>
* </#if>
*
* @param annotationMethod
* @return
*/
protected boolean isApplicableAnnotationMethod(Method annotationMethod) {
return annotationMethod != null
&& annotationMethod.getReturnType() == String.class;
}
/**
*
* <#if locale="en">
* <p>
* Get template path from the annotation class.
* </p>
* <#else>
* <p>
* </p>
* </#if>
*
* @param c
* @return
*/
protected Method getTemplatePathReturnMethod(Class<? extends Annotation> c) {
return MethodUtil.getDeclaredMethodNoException(c, "value",
Constants.EMPTY_CLASS_ARRAY);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(this.getClass().getSimpleName()).append("@").append(
this.hashCode()).append("[");
builder.append("methodName=").append(this.methodName).append(",");
builder.append("templatePath=").append(this.templatePath).append(",");
builder.append("annotationCounts=").append(this.annotationCounts);
builder.append("]");
return new String(builder);
}
}