blob: a89418ee6f35313f096c151fe38a9d567799caad [file] [log] [blame]
/*
* Copyright 2006 Google Inc.
*
* 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.google.gwt.dev.util.xml;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Represents metadata about a parameter in a handler method in a class derived
* from {@link Schema}.
*/
public final class HandlerParam {
/**
* Looks for a field of the form [methodName]_[paramIndex]_[attrName].
*/
public static HandlerParam create(Method method, String normalizedTagName,
int paramIndex) {
Class<?> paramType = method.getParameterTypes()[paramIndex];
Field[] fields = method.getDeclaringClass().getDeclaredFields();
String fieldNamePrefix = normalizedTagName + "_" + (paramIndex + 1);
Field matchingField = null;
String fieldName = null;
for (int i = 0, n = fields.length; i < n; ++i) {
Field testField = fields[i];
fieldName = testField.getName();
if (fieldName.startsWith(fieldNamePrefix)) {
matchingField = testField;
break;
}
}
if (matchingField == null) {
throw new IllegalArgumentException("Expecting a meta field with prefix '"
+ fieldNamePrefix + "'");
}
int under = fieldName.indexOf("_", fieldNamePrefix.length());
if (under == -1) {
// Not a valid signature.
//
throw new IllegalArgumentException(
"Expecting a normalized attribute name suffix (e.g. \"_attr_name\") on field '"
+ fieldName + "'");
}
// Infer the associated attribute name.
//
String normalizedAttrName = fieldName.substring(under + 1);
// GWT fields values must be of type String.
//
if (!String.class.equals(matchingField.getType())) {
// Type mismatch.
//
throw new IllegalArgumentException("GWT field '" + fieldName
+ "' must be of type String");
}
// Instantiate one.
//
matchingField.setAccessible(true);
HandlerParam handlerParam = new HandlerParam(paramType, matchingField,
normalizedAttrName);
return handlerParam;
}
private final Class<?> paramType;
private final Field metaField;
private final boolean isOptional;
private final String normalizedAttrName;
private HandlerParam(Class<?> paramType, Field metaField,
String normalizedAttrName) {
this.isOptional = normalizedAttrName.endsWith("$");
if (isOptional) {
normalizedAttrName = normalizedAttrName.substring(0, normalizedAttrName.length() - 1);
}
this.paramType = paramType;
this.metaField = metaField;
this.normalizedAttrName = normalizedAttrName;
}
/**
* Called while parsing to get the default value for an attribute.
*/
public String getDefaultValue(Schema schema) {
Throwable caught = null;
try {
return (String) metaField.get(schema);
} catch (IllegalArgumentException e) {
caught = e;
} catch (IllegalAccessException e) {
caught = e;
}
throw new IllegalStateException(
"Unable to get attribute default value from meta field '"
+ metaField.getName() + "'", caught);
}
public String getNormalizedName() {
return normalizedAttrName;
}
public Class<?> getParamType() {
return paramType;
}
public boolean isOptional() {
return isOptional;
}
}