package jalse.entities.functions; import static jalse.attributes.Attributes.newNamedUnknownType; import static jalse.entities.functions.Functions.checkHasReturnType; import static jalse.entities.functions.Functions.checkNoParams; import static jalse.entities.functions.Functions.checkNotDefault; import static jalse.entities.functions.Functions.firstGenericTypeArg; import static jalse.entities.functions.Functions.isPrimitive; import static jalse.entities.functions.Functions.returnTypeIs; import static jalse.entities.functions.Functions.toClass; import static jalse.entities.functions.Functions.wrap; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Optional; import jalse.attributes.AttributeContainer; import jalse.entities.DefaultEntityProxyFactory; import jalse.entities.annotations.GetAttribute; import jalse.entities.methods.GetAttributeMethod; /** * This is a method function for {@link GetAttribute} annotation. It will resolve an * {@link GetAttributeMethod} to be used by the entity typing system.<br> * <br> * The next example signatures will resolve to * {@link AttributeContainer#getAttribute(String, jalse.attributes.AttributeType)} supplied with the * name {@code scary} and type {@code Boolean}. * * <pre> * <code> * {@code @GetAttribute(name = "scary")} * Boolean isScary(); * * {@code @GetAttribute} * Boolean isScary(); * </code> * </pre> * * The next example signatures will resolve to * {@link AttributeContainer#getOptAttribute(String, jalse.attributes.AttributeType)} supplied with * the name {@code scary} and type {@code Boolean}. * * <pre> * <code> * {@code @GetAttribute(name = "scary")} * Optional{@code <Boolean>} isScary(); * * {@code @GetAttribute} * Optional{@code <Boolean>} isScary(); * </code> * </pre> * * NOTE: This function will throw exceptions if {@link GetAttribute} is present but the method * signature is invalid. * * @author Elliot Ford * * @see DefaultEntityProxyFactory * */ public class GetAttributeFunction implements EntityMethodFunction { private static final String IS_PREFIX = "is"; private static final String GET_PREFIX = "get"; @Override public GetAttributeMethod apply(final Method m) { // Check for annotation final GetAttribute annonation = m.getAnnotation(GetAttribute.class); if (annonation == null) { return null; } // Basic check method signature checkHasReturnType(m); checkNotDefault(m); checkNoParams(m); // Work out attribute name String name = annonation.name(); if (name.length() == 0) { String methodName = m.getName(); if (methodName.startsWith(GET_PREFIX)) { // getAmmount -> Ammount methodName = methodName.substring(GET_PREFIX.length()); } else if (methodName.startsWith(IS_PREFIX)) { // isScary -> Scary methodName = methodName.substring(IS_PREFIX.length()); } // Scary -> scary name = Character.toLowerCase(methodName.charAt(0)) + methodName.substring(1); } // Check suitable name if (name.length() == 0) { // Must have a name. throw new IllegalArgumentException("Attribute name is empty"); } Type attrType = m.getGenericReturnType(); boolean primitive = false; // Check not primitive if (isPrimitive(attrType)) { attrType = wrap(toClass(attrType)); primitive = true; } // Check is optional final boolean optional = returnTypeIs(m, Optional.class); if (optional) { attrType = firstGenericTypeArg(attrType); } // Create get attribute method return new GetAttributeMethod(newNamedUnknownType(name, attrType), primitive, optional); } }