
com.anrisoftware.globalpom.reflection.annotationclass.AnnotationClass Maven / Gradle / Ivy
/*
* Copyright 2016 Erwin Müller
*
* 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.anrisoftware.globalpom.reflection.annotationclass;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import java.beans.PropertyVetoException;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import javax.inject.Inject;
import org.apache.commons.lang3.builder.Builder;
import com.anrisoftware.globalpom.reflection.annotations.AnnotationAccess;
import com.anrisoftware.globalpom.reflection.annotations.AnnotationAccessFactory;
import com.anrisoftware.globalpom.reflection.beans.BeanAccess;
import com.anrisoftware.globalpom.reflection.beans.BeanAccessFactory;
import com.anrisoftware.globalpom.reflection.beans.BeanFactory;
import com.google.inject.assistedinject.Assisted;
/**
* Creates an instance from an annotation attribute.
*
* If the parent object have a field that the attribute name references then the
* field's value is returned. If the field have no instance, the instance is
* created with the default constructor and the field is set. If the attribute
* name is set to a class type, the class type is instantiated and returned.
*
* The attribute is suffixed with "Class" so that it reference the class type
* that should be instantiated.
*
*
Examples
*
* With class type field
*
*
* class Bean {
*
* @SomeAnnotation(model = "someModel")
* public Object someField;
*
* public SomeModel someModel;
* }
*
* public SomeModel createModel(Bean bean, Field someField) {
* return create(bean, SomeAnnotation.class, someField).forAttribute("model")
* .build();
* }
*
*
* With class type
*
*
* class Bean {
*
* @SomeAnnotation(modelClass = SomeModel.class)
* public Object someField;
* }
*
* public SomeModel createModel(Bean bean, Field someField) {
* return create(bean, SomeAnnotation.class, someField).forAttribute("model")
* .build();
* }
*
*
* @author Erwin Mueller, [email protected]
* @since 1.5
*/
public class AnnotationClass implements Builder {
/**
* @see AnnotationClassFactory#create(Object, Class, AccessibleObject)
*/
@SuppressWarnings("unchecked")
public static AnnotationClass create(Object parent,
Class extends Annotation> annotation, AccessibleObject object) {
return (AnnotationClass) AnnotationClassModule.getInjector()
.getInstance(AnnotationClassFactory.class)
.create(parent, annotation, object);
}
private final AnnotationClassLogger log;
private final BeanAccessFactory beanAccessFactory;
private final AnnotationAccess fieldAnnotation;
private final BeanFactory beanFactory;
private String attributeName;
private final Object parent;
private ClassType defaultValue;
/**
* @see AnnotationClassFactory#create(Class, AccessibleObject)
*/
@Inject
AnnotationClass(AnnotationClassLogger logger,
AnnotationAccessFactory accessFactory,
BeanAccessFactory beanAccessFactory, BeanFactory beanFactory,
@Assisted Object parent,
@Assisted Class extends Annotation> annotation,
@Assisted AccessibleObject object) {
this.log = logger;
this.parent = parent;
this.fieldAnnotation = accessFactory.create(annotation, object);
this.beanAccessFactory = beanAccessFactory;
this.beanFactory = beanFactory;
}
/**
* Sets the default value that is returned if neither the object field nor
* the object class is set in the annotation.
*
* @param defaultValue
* the default value {@link Object} or {@code null}.
*
* @return this {@link AnnotationClass}.
*/
public AnnotationClass withDefault(ClassType defaultValue) {
this.defaultValue = defaultValue;
return this;
}
/**
* Sets the attribute name of the annotation that is either the name of the
* field or the class type.
*
* @param name
* the attribute name.
*
* @return this {@link AnnotationClass}.
*
* @throws NullPointerException
* if the specified name is {@code null}.
*
* @throws IllegalArgumentException
* if the specified name is empty.
*/
public AnnotationClass forAttribute(String name) {
this.attributeName = name;
return this;
}
/**
* Returns the class type object.
*
* @returns the field if the field name was specified; instantiates and
* returns the class object if the class type was specified;
* {@code null} if neither was specified in the annotation.
*
* @throws NullPointerException
* if the attribute name is {@code null}.
*
* @throws IllegalArgumentException
* if the specified attribute name is empty.
*/
@Override
public ClassType build() {
log.checkAttributeName(attributeName);
return createInstance();
}
private ClassType createInstance() {
String fieldName = fieldAnnotation.getValue(attributeName);
if (!isEmpty(fieldName)) {
return createFromField(fieldName);
} else {
return createModelClass();
}
}
private ClassType createFromField(String fieldName) {
BeanAccess access = beanAccessFactory.create(fieldName, parent);
ClassType value = access.getValue();
return value == null ? createModelFromField(access) : value;
}
@SuppressWarnings("unchecked")
private ClassType createModelFromField(BeanAccess access) {
Class extends ClassType> type;
type = (Class extends ClassType>) access.getType();
ClassType model = beanFactory.create(type);
try {
access.setValue(model);
return model;
} catch (PropertyVetoException e) {
throw new NullPointerException();
}
}
private ClassType createModelClass() {
ClassType model = null;
String name = getAttributeClass();
if (fieldAnnotation.haveValue(name)) {
model = createModelClass0(name);
}
return model;
}
private ClassType createModelClass0(String name) {
Class extends ClassType>[] type = fieldAnnotation.getValue(name);
if (type.length < 1) {
return defaultValue;
}
log.checkClassAttribute(type, attributeName);
return beanFactory.create(type[0]);
}
private String getAttributeClass() {
return attributeName + "Class";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy