com.talk2object.plum.interaction.viewgeneneration.ViewFactoryImpl Maven / Gradle / Ivy
package com.talk2object.plum.interaction.viewgeneneration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.filter.AssignableTypeFilter;
import com.talk2object.plum.interaction.viewbuilder.AnnotationViewBuilder;
import com.talk2object.plum.interaction.viewbuilder.ObjectViewBuilder;
import com.talk2object.plum.interaction.viewbuilder.SelfViewBuilder;
import com.talk2object.plum.interaction.viewbuilder.bean.BeanViewBuilder;
import com.talk2object.plum.view._abstract.window.UIComponent;
import com.talk2object.util.ClassAssignmentUtils;
/**
* TODO add similarModelClass cache for later lookup.
*
* @author jack
*
*/
public class ViewFactoryImpl implements ViewFactory {
private static Logger logger = Logger.getLogger(ViewFactoryImpl.class);
private String basePackage;
// key is full class name
private Map builderMap = new HashMap();
// special builders
private ViewBuilder annotationViewBuilder = new AnnotationViewBuilder();
private ViewBuilder beanViewBuilder = new BeanViewBuilder();
private ViewBuilder objectViewBuilder = new ObjectViewBuilder();
// private ModelAdapterRegistry modelAdapterRegistry = new
// ModelAdapterRegistry();
public void scanDomainObjects() {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
false);
// provider.addIncludeFilter(new AssignableTypeFilter(forClass));
// Had to add this line
provider.setResourceLoader(new PathMatchingResourcePatternResolver());
provider.addIncludeFilter(new AssignableTypeFilter(ViewBuilder.class));
Set candidates = provider
.findCandidateComponents(basePackage);
for (BeanDefinition def : candidates) {
try {
Class clazz = Class.forName(def.getBeanClassName());
AbstractViewBuilder builder = (AbstractViewBuilder) clazz
.newInstance();
if (builder.getModelClass() != null) {
logger.info("find view builder: " + builder);
register(builder.getModelClass(), builder);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public String getBasePackage() {
return basePackage;
}
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
public static void main(String[] args) {
ViewFactoryImpl fact = new ViewFactoryImpl();
fact.setBasePackage("com/talk2object/plum");
fact.scanDomainObjects();
}
@Override
public void register(Class modelClass, AbstractViewBuilder builder) {
builderMap.put(modelClass, builder);
}
@Override
public UIComponent create(Object model, Class modelClass,
String viewClassExpressions, ViewBuildContext context,
UIComponent parentView) {
String[] viewClassExprs = viewClassExpressions.split(" ");
ViewBuilder builder = builderMap.get(modelClass);
if (builder == null)
throw new RuntimeException("No view builder is found for model:"
+ modelClass);
return build(builder, model, viewClassExprs, context, parentView);
}
@Override
public UIComponent create(Object model, BuilderMatchPolicy policy,
String viewClassExpressions, ViewBuildContext context,
UIComponent parentView) {
ViewBuilder builder = findViewBuilder(model, policy);
if (builder == null)
throw new RuntimeException("No view builder is found for model:"
+ model.getClass());
String[] viewClassExprs = viewClassExpressions.split(" ");
return build(builder, model, viewClassExprs, context, parentView);
}
@Override
public UIComponent create(Object model, BuilderMatchPolicy policy,
String[] viewClassExpressionArray, ViewBuildContext context,
UIComponent parentView) {
ViewBuilder builder = findViewBuilder(model, policy);
if (builder == null)
throw new RuntimeException("No view builder is found for model:"
+ model.getClass());
return build(builder, model, viewClassExpressionArray, context,
parentView);
}
private ViewBuilder findViewBuilder(Object model, BuilderMatchPolicy policy) {
Class modelClass = model.getClass();
ViewBuilder builder = null;
ViewBuilder registeredBuilder = builderMap.get(model.getClass());
// 1 registered and important
if (registeredBuilder != null && registeredBuilder.isImportant())
return registeredBuilder;
// 2. Visible interface
if (model instanceof Visible) {
ViewBuilder selfBuilder = new SelfViewBuilder();
return selfBuilder;
}
// 3. annotated
if (AnnotationViewBuilder.hasViewAnnotation(modelClass)) {
return annotationViewBuilder;
}
// registered
if (registeredBuilder != null)
return registeredBuilder;
// still not found
switch (policy) {
case SUBCLASS_OBJECT:
modelClass = findMostSimilarModelClass(model.getClass(), true);
builder = builderMap.get(modelClass);
if (builder == null)
builder = objectViewBuilder;
break;
case SUBCLASS_BEAN_OBJECT:
modelClass = findMostSimilarModelClass(model.getClass(), true);
builder = builderMap.get(modelClass);
if (builder == null)
builder = beanViewBuilder;
if (builder == null)
builder = objectViewBuilder;
break;
case BEAN:
builder = beanViewBuilder;
break;
}
return builder;
}
private UIComponent build(ViewBuilder builder, Object model,
String[] viewClassExpressions, ViewBuildContext context,
UIComponent parentView) {
for (String viewClassExpr : viewClassExpressions) {
UIComponent view = builder.build(model, viewClassExpr, context,
parentView);
if (view != null)
{
return view;
}
}
return null;
}
private Class findMostSimilarModelClass(Class clazz,
boolean excludeObjectClass) {
// find the smallest cost
Class mostSimilarModelClass = null;
int smallestCost = Integer.MAX_VALUE;
try {
for (Class targetClass : builderMap.keySet()) {
if (excludeObjectClass && targetClass.equals(Object.class))
continue;
int cost = ClassAssignmentUtils.getAssignmentCost(targetClass,
clazz);
if (cost >= 0 && cost < smallestCost) {
smallestCost = cost;
mostSimilarModelClass = targetClass;
}
}
return mostSimilarModelClass;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy