/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.fib.model; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.logging.Logger; import org.openflexo.antar.binding.BindingDefinition; import org.openflexo.antar.binding.BindingDefinition.BindingDefinitionType; import org.openflexo.antar.binding.GenericArrayTypeImpl; import org.openflexo.antar.binding.ParameterizedTypeImpl; import org.openflexo.antar.binding.TypeUtils; import org.openflexo.antar.binding.WilcardTypeImpl; import org.openflexo.fib.controller.FIBMultipleValuesDynamicModel; import org.openflexo.fib.model.validation.FixProposal; import org.openflexo.fib.model.validation.ValidationError; import org.openflexo.fib.model.validation.ValidationIssue; import org.openflexo.fib.model.validation.ValidationReport; import org.openflexo.fib.model.validation.ValidationRule; import org.openflexo.toolbox.StringUtils; public abstract class FIBMultipleValues extends FIBWidget { private static final Logger logger = Logger.getLogger(FIBMultipleValues.class.getPackage().getName()); public static enum Parameters implements FIBModelAttribute { staticList, list, array, showIcon, showText, iteratorClass, autoSelectFirstRow } public BindingDefinition LIST = new BindingDefinition("list", new ParameterizedTypeImpl(List.class, new WilcardTypeImpl(Object.class)), BindingDefinitionType.GET, false) { @Override public Type getType() { return getListBindingType(); } }; public BindingDefinition ARRAY = new BindingDefinition("array", new GenericArrayTypeImpl(new WilcardTypeImpl(Object.class)), BindingDefinitionType.GET, false) { @Override public Type getType() { return getArrayBindingType(); } }; private BindingDefinition DATA = new BindingDefinition("data", Object.class, BindingDefinitionType.GET_SET, false) { @Override public Type getType() { return getDataType(); }; }; private String staticList; private DataBinding list; private DataBinding array; private Class iteratorClass; private Class expectedIteratorClass; private boolean showIcon = false; private boolean showText = true; private boolean autoSelectFirstRow = false; public FIBMultipleValues() { } private Type LIST_BINDING_TYPE; private Type ARRAY_BINDING_TYPE; private Type getListBindingType() { if (LIST_BINDING_TYPE == null) { LIST_BINDING_TYPE = new ParameterizedTypeImpl(List.class, new WilcardTypeImpl(getIteratorClass())); } return LIST_BINDING_TYPE; } private Type getArrayBindingType() { if (ARRAY_BINDING_TYPE == null) { ARRAY_BINDING_TYPE = new GenericArrayTypeImpl(new WilcardTypeImpl(getIteratorClass())); } return ARRAY_BINDING_TYPE; } public DataBinding getList() { if (list == null) { list = new DataBinding(this, Parameters.list, LIST); } return list; } public void setList(DataBinding list) { list.setOwner(this); list.setBindingAttribute(Parameters.list); list.setBindingDefinition(LIST); this.list = list; } public DataBinding getArray() { if (array == null) { array = new DataBinding(this, Parameters.array, ARRAY); } return array; } public void setArray(DataBinding array) { array.setOwner(this); array.setBindingAttribute(Parameters.array); array.setBindingDefinition(ARRAY); this.array = array; } @Override public void finalizeDeserialization() { super.finalizeDeserialization(); if (list != null) { list.finalizeDeserialization(); } if (array != null) { array.finalizeDeserialization(); } } public boolean isStaticList() { return (getList() == null || !getList().isSet()) && (getArray() == null || !getArray().isSet()) && StringUtils.isNotEmpty(getStaticList()); } public boolean isEnumType() { if (getData() != null && getData().getBinding() != null) { Type type = getData().getBinding().getAccessedType(); if (type instanceof Class && ((Class) type).isEnum()) { return true; } } if (iteratorClass != null && iteratorClass.isEnum()) { return true; } if (expectedIteratorClass != null && expectedIteratorClass.isEnum()) { return true; } return false; } public Class getIteratorClass() { if (isStaticList()) { return String.class; } if (iteratorClass == null) { if (expectedIteratorClass != null) { return expectedIteratorClass; } else { return Object.class; } } return iteratorClass; } public void setIteratorClass(Class iteratorClass) { FIBAttributeNotification<Class> notification = requireChange(Parameters.iteratorClass, iteratorClass); if (notification != null) { LIST_BINDING_TYPE = null; ARRAY_BINDING_TYPE = null; this.iteratorClass = iteratorClass; hasChanged(notification); } } @Override public Type getDataType() { if (isStaticList()) { return String.class; } if (iteratorClass != null) { return iteratorClass; } return super.getDataType(); } @Override public Type getFormattedObjectType() { if (isStaticList()) { return String.class; } if (iteratorClass != null) { return iteratorClass; } return getDataType(); } @Override public BindingDefinition getDataBindingDefinition() { return DATA; } /*@Override public final Type getDefaultDataClass() { return getIteratorClass(); }*/ @Override public final Type getDefaultDataClass() { return Object.class; } @Override public void notifyBindingChanged(DataBinding binding) { // logger.info("******* notifyBindingChanged with "+binding); if (binding == getList()) { if (getList() != null && getList().getBinding() != null) { Type accessedType = getList().getBinding().getAccessedType(); if (accessedType instanceof ParameterizedType && ((ParameterizedType) accessedType).getActualTypeArguments().length > 0) { Class newIteratorClass = TypeUtils.getBaseClass(((ParameterizedType) accessedType).getActualTypeArguments()[0]); if (getIteratorClass() == null || !TypeUtils.isClassAncestorOf(newIteratorClass, getIteratorClass())) { setIteratorClass(newIteratorClass); } } } } else if (binding == getArray()) { if (getArray() != null && getArray().getBinding() != null) { Type accessedType = getArray().getBinding().getAccessedType(); if (accessedType instanceof GenericArrayType) { Class newIteratorClass = TypeUtils.getBaseClass(((GenericArrayType) accessedType).getGenericComponentType()); if (getIteratorClass() == null || !TypeUtils.isClassAncestorOf(newIteratorClass, getIteratorClass())) { setIteratorClass(newIteratorClass); } } } } else if (binding == getData()) { if (getData() != null && getData().getBinding() != null) { Type accessedType = getData().getBinding().getAccessedType(); /*if (accessedType instanceof Class && ((Class)accessedType).isEnum()) { setIteratorClass((Class)accessedType); }*/ if (accessedType instanceof Class) { expectedIteratorClass = (Class) accessedType; } } } else if (binding == getFormat()) { setChanged(); notifyChange(FIBWidget.Parameters.format); } } public String getStaticList() { return staticList; } public final void setStaticList(String staticList) { FIBAttributeNotification<String> notification = requireChange(Parameters.staticList, staticList); if (notification != null) { this.staticList = staticList; LIST_BINDING_TYPE = null; ARRAY_BINDING_TYPE = null; // logger.info("FIBMultiple: setStaticList with " + staticList); hasChanged(notification); } } public Boolean getShowIcon() { return showIcon; } public void setShowIcon(Boolean showIcon) { FIBAttributeNotification<Boolean> notification = requireChange(Parameters.showIcon, showIcon); if (notification != null) { this.showIcon = showIcon; hasChanged(notification); } } public Boolean getShowText() { return showText; } public void setShowText(Boolean showText) { FIBAttributeNotification<Boolean> notification = requireChange(Parameters.showText, showText); if (notification != null) { this.showText = showText; hasChanged(notification); } } @Override public Type getDynamicAccessType() { Type[] args = new Type[2]; args[0] = getDataType(); args[1] = getIteratorClass(); return new ParameterizedTypeImpl(FIBMultipleValuesDynamicModel.class, args); } public boolean getAutoSelectFirstRow() { return autoSelectFirstRow; } public void setAutoSelectFirstRow(boolean autoSelectFirstRow) { FIBAttributeNotification<Boolean> notification = requireChange(Parameters.autoSelectFirstRow, autoSelectFirstRow); if (notification != null) { this.autoSelectFirstRow = autoSelectFirstRow; hasChanged(notification); } } @Override protected void applyValidation(ValidationReport report) { super.applyValidation(report); performValidation(FIBMultipleValuesMustDefineValueRange.class, report); performValidation(ListBindingMustBeValid.class, report); performValidation(ArrayBindingMustBeValid.class, report); } public static class FIBMultipleValuesMustDefineValueRange extends ValidationRule<FIBMultipleValuesMustDefineValueRange, FIBMultipleValues> { public FIBMultipleValuesMustDefineValueRange() { super(FIBMultipleValues.class, "widget_must_define_values_range_(either_static_list_or_dynamic_list_or_array_or_enumeration)"); } @Override public ValidationIssue<FIBMultipleValuesMustDefineValueRange, FIBMultipleValues> applyValidation(FIBMultipleValues object) { if (StringUtils.isEmpty(object.getStaticList()) && !object.getList().isSet() && !object.getArray().isSet() && !object.isEnumType()) { GenerateDefaultStaticList fixProposal = new GenerateDefaultStaticList(); return new ValidationError<FIBMultipleValuesMustDefineValueRange, FIBMultipleValues>(this, object, "widget_does_not_define_any_values_range_(either_static_list_or_dynamic_list_or_array_or_enumeration)", fixProposal); } return null; } protected static class GenerateDefaultStaticList extends FixProposal<FIBMultipleValuesMustDefineValueRange, FIBMultipleValues> { public GenerateDefaultStaticList() { super("generate_default_static_list"); } @Override protected void fixAction() { getObject().setStaticList("Item 1 ,Item 2 ,Item 3 "); } } } public static class ListBindingMustBeValid extends BindingMustBeValid<FIBMultipleValues> { public ListBindingMustBeValid() { super("'list'_binding_is_not_valid", FIBMultipleValues.class); } @Override public DataBinding getBinding(FIBMultipleValues object) { return object.getList(); } @Override public BindingDefinition getBindingDefinition(FIBMultipleValues object) { return object.LIST; } } public static class ArrayBindingMustBeValid extends BindingMustBeValid<FIBMultipleValues> { public ArrayBindingMustBeValid() { super("'array'_binding_is_not_valid", FIBMultipleValues.class); } @Override public DataBinding getBinding(FIBMultipleValues object) { return object.getArray(); } @Override public BindingDefinition getBindingDefinition(FIBMultipleValues object) { return object.ARRAY; } } }