package org.nocket.gen.domain;
import gengui.annotations.Choicetype;
import gengui.domain.AbstractDomainReference;
import gengui.util.ReflectionUtil;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.nocket.gen.domain.element.ButtonElement;
import org.nocket.gen.domain.element.CheckboxPropertyElement;
import org.nocket.gen.domain.element.ChoicerPropertyElement;
import org.nocket.gen.domain.element.HeadlineElement;
import org.nocket.gen.domain.element.HiddenPropertyElement;
import org.nocket.gen.domain.element.MultivalueButtonElement;
import org.nocket.gen.domain.element.MultivaluePropertyElement;
import org.nocket.gen.domain.element.ResourceElement;
import org.nocket.gen.domain.element.SimplePropertyElement;
import org.nocket.gen.domain.ref.WrappedDomainReferenceI;
import org.nocket.gen.domain.visitor.DomainElementVisitorI;
import org.nocket.gen.page.element.synchronizer.SynchronizerHelper;
/**
* DomainProcessorStrategy traverse over domain object and calls visitor,
*
* @author meis026
*
* @param <E>
*/
public class DomainProcessorStrategy<E extends AbstractDomainReference> {
protected DomainElementVisitorI<E> visitor;
protected void process(DMDWebGenContext<E> context, WrappedDomainReferenceI<E> ref) {
processDomainClass(context, ref);
}
protected void processDomainClass(DMDWebGenContext<E> context, WrappedDomainReferenceI<E> ref) {
Method[] propertyMethods = ReflectionUtil.extractOrderedPropertyMethods(ref.getRef(), true);
if (propertyMethods == null) {
return;
}
List<Method> methodList = Arrays.asList(propertyMethods);
processPass(context, ref, methodList);
visitor.finish();
}
protected void processPass(DMDWebGenContext<E> context, WrappedDomainReferenceI<E> ref, List<Method> methods) {
List<Method> subPropertyMethods = new ArrayList<Method>();
Map<Method, Boolean> multivaluePropertyMethods_withButtons = new HashMap<Method, Boolean>();
// 1. Choicer and Simple
for (Method method : methods) {
if (ReflectionUtil.isHiddenProperty(method.getName(), ref.getRef())) {
new HiddenPropertyElement<E>(ref, method).accept(visitor);
} else if (!ReflectionUtil.isSimpleType(method) && !ReflectionUtil.isMultivalued(method)
&& !ReflectionUtil.hasChoicer(ref.getRef(), method)) {
subPropertyMethods.add(method);
} else {
if (ReflectionUtil.isMultivalued(method) && !ReflectionUtil.hasChoicer(ref.getRef(), method)) {
multivaluePropertyMethods_withButtons.put(method, true);
} else if (method.getReturnType().isEnum() || ReflectionUtil.hasChoicer(ref.getRef(), method)) {
Choicetype.Type ct = ReflectionUtil.getChoiceType(context.getRefFactory()
.getRootReference()
.getRef(), method);
if (ct != null && ct == Choicetype.Type.TABLE) {
multivaluePropertyMethods_withButtons.put(method, false);
} else {
// choicer
new ChoicerPropertyElement<E>(ref, method).accept(visitor);
}
} else {
if (SynchronizerHelper.isBooleanType(method)) {
// checkbox property
new CheckboxPropertyElement<E>(ref, method).accept(visitor);
} else {
// simple property
new SimplePropertyElement<E>(ref, method).accept(visitor);
}
}
}
}
// 2. Complex Members
for (Method method : subPropertyMethods) {
// sub properties
WrappedDomainReferenceI<E> subRef = context.getRefFactory().newSubReference(ref, method);
new HeadlineElement<E>(ref, method).accept(visitor);
processDomainClass(context, subRef);
visitor.visitFieldsetClose();
}
// 3. Tables (with Table Buttons)
for (Entry<Method, Boolean> e : multivaluePropertyMethods_withButtons.entrySet()) {
Method method = e.getKey();
boolean withButtons = e.getValue();
// collection
new HeadlineElement<E>(ref, method).accept(visitor);
List<MultivalueButtonElement<E>> multivalueButtons = new ArrayList<MultivalueButtonElement<E>>();
WrappedDomainReferenceI<E> subRef = context.getRefFactory().newSubReference(ref, method);
if (withButtons) {
// collection buttons
Method[] buttonMethods = extractOrderedCollectionButtonMethods(subRef);
for (Method subMethod : buttonMethods) {
multivalueButtons.add(new MultivalueButtonElement<E>(subRef, subMethod));
}
Method remover = ReflectionUtil.findMethod(ref.getClassRef().getDomainClass(),
ReflectionUtil.REMOVER_PREFIX, ReflectionUtil.removePrefix(method.getName()));
if (remover != null) {
multivalueButtons.add(new MultivalueButtonElement<E>(ref, remover));
}
}
new MultivaluePropertyElement<E>(ref, method, subRef, multivalueButtons).accept(visitor);
visitor.visitFieldsetClose();
}
// 4. Simple Buttons
Method[] buttonMethods = extractOrderedButtonMethods(ref, true);
for (Method method : buttonMethods) {
if (!method.getName().startsWith(ReflectionUtil.REMOVER_PREFIX)) {
if (isResource(method)) {
new ResourceElement<E>(ref, method).accept(visitor);
} else {
new ButtonElement<E>(ref, method).accept(visitor);
}
}
}
}
protected boolean isResource(Method method) {
return method.getReturnType() != null
&& (InputStream.class.isAssignableFrom(method.getReturnType()) || File.class.isAssignableFrom(method
.getReturnType()));
}
protected Method[] extractOrderedCollectionButtonMethods(WrappedDomainReferenceI<E> subRef) {
return ReflectionUtil.extractOrderedCollectionButtonMethods(subRef.getRef());
}
protected Method[] extractOrderedButtonMethods(WrappedDomainReferenceI<E> ref, boolean withCollectionMethods) {
return ReflectionUtil.extractOrderedButtonMethods(ref.getRef(), withCollectionMethods);
}
}