/* * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved. * * This file is part of the Jspresso framework. * * Jspresso is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jspresso 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Jspresso. If not, see <http://www.gnu.org/licenses/>. */ package org.jspresso.framework.view; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.Format; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TimeZone; import org.jspresso.framework.action.ActionContextConstants; import org.jspresso.framework.action.IAction; import org.jspresso.framework.action.IActionHandler; import org.jspresso.framework.action.IActionHandlerAware; import org.jspresso.framework.binding.AbstractCompositeValueConnector; import org.jspresso.framework.binding.ConnectorHelper; import org.jspresso.framework.binding.ICollectionConnector; import org.jspresso.framework.binding.ICollectionConnectorListProvider; import org.jspresso.framework.binding.ICollectionConnectorProvider; import org.jspresso.framework.binding.ICompositeValueConnector; import org.jspresso.framework.binding.IConfigurableCollectionConnectorListProvider; import org.jspresso.framework.binding.IConfigurableCollectionConnectorProvider; import org.jspresso.framework.binding.IConfigurableConnectorFactory; import org.jspresso.framework.binding.IMvcBinder; import org.jspresso.framework.binding.IRenderableCompositeValueConnector; import org.jspresso.framework.binding.IValueConnector; import org.jspresso.framework.binding.masterdetail.IModelCascadingBinder; import org.jspresso.framework.binding.model.IModelConnectorFactory; import org.jspresso.framework.binding.model.ModelRefPropertyConnector; import org.jspresso.framework.model.component.IComponentCollectionFactory; import org.jspresso.framework.model.descriptor.EDateType; import org.jspresso.framework.model.descriptor.EDuration; import org.jspresso.framework.model.descriptor.IBinaryPropertyDescriptor; import org.jspresso.framework.model.descriptor.IBooleanPropertyDescriptor; import org.jspresso.framework.model.descriptor.ICollectionDescriptorProvider; import org.jspresso.framework.model.descriptor.ICollectionPropertyDescriptor; import org.jspresso.framework.model.descriptor.IColorPropertyDescriptor; import org.jspresso.framework.model.descriptor.IComponentDescriptor; import org.jspresso.framework.model.descriptor.IDatePropertyDescriptor; import org.jspresso.framework.model.descriptor.IDecimalPropertyDescriptor; import org.jspresso.framework.model.descriptor.IDurationPropertyDescriptor; import org.jspresso.framework.model.descriptor.IEnumerationPropertyDescriptor; import org.jspresso.framework.model.descriptor.IHtmlPropertyDescriptor; import org.jspresso.framework.model.descriptor.IImageBinaryPropertyDescriptor; import org.jspresso.framework.model.descriptor.IImageUrlPropertyDescriptor; import org.jspresso.framework.model.descriptor.IIntegerPropertyDescriptor; import org.jspresso.framework.model.descriptor.IModelDescriptor; import org.jspresso.framework.model.descriptor.INumberPropertyDescriptor; import org.jspresso.framework.model.descriptor.IPasswordPropertyDescriptor; import org.jspresso.framework.model.descriptor.IPercentPropertyDescriptor; import org.jspresso.framework.model.descriptor.IPropertyDescriptor; import org.jspresso.framework.model.descriptor.IReferencePropertyDescriptor; import org.jspresso.framework.model.descriptor.IRelationshipEndPropertyDescriptor; import org.jspresso.framework.model.descriptor.ISourceCodePropertyDescriptor; import org.jspresso.framework.model.descriptor.IStringPropertyDescriptor; import org.jspresso.framework.model.descriptor.ITextPropertyDescriptor; import org.jspresso.framework.model.descriptor.ITimeAwarePropertyDescriptor; import org.jspresso.framework.model.descriptor.ITimePropertyDescriptor; import org.jspresso.framework.security.EAuthorization; import org.jspresso.framework.security.ISecurable; import org.jspresso.framework.security.ISecurityHandlerAware; import org.jspresso.framework.security.ISubjectAware; import org.jspresso.framework.util.collection.IPageable; import org.jspresso.framework.util.event.IItemSelectable; import org.jspresso.framework.util.event.IItemSelectionListener; import org.jspresso.framework.util.event.ISelectionChangeListener; import org.jspresso.framework.util.event.IValueChangeListener; import org.jspresso.framework.util.event.IValueChangeSource; import org.jspresso.framework.util.event.ItemSelectionEvent; import org.jspresso.framework.util.event.SelectionChangeEvent; import org.jspresso.framework.util.event.ValueChangeEvent; import org.jspresso.framework.util.format.DurationFormatter; import org.jspresso.framework.util.format.EnumerationFormatter; import org.jspresso.framework.util.format.FormatAdapter; import org.jspresso.framework.util.format.IFormatter; import org.jspresso.framework.util.format.NullableSimpleDateFormat; import org.jspresso.framework.util.gate.IGate; import org.jspresso.framework.util.gate.ModelTrackingGate; import org.jspresso.framework.util.gui.Dimension; import org.jspresso.framework.util.gui.ERenderingOptions; import org.jspresso.framework.util.gui.IClientTypeAware; import org.jspresso.framework.util.i18n.ITranslationProvider; import org.jspresso.framework.util.lang.ICloneable; import org.jspresso.framework.util.lang.ObjectUtils; import org.jspresso.framework.view.action.IDisplayableAction; import org.jspresso.framework.view.descriptor.IActionViewDescriptor; import org.jspresso.framework.view.descriptor.IBorderViewDescriptor; import org.jspresso.framework.view.descriptor.ICardViewDescriptor; import org.jspresso.framework.view.descriptor.ICollectionViewDescriptor; import org.jspresso.framework.view.descriptor.IComponentViewDescriptor; import org.jspresso.framework.view.descriptor.ICompositeTreeLevelDescriptor; import org.jspresso.framework.view.descriptor.ICompositeViewDescriptor; import org.jspresso.framework.view.descriptor.IConstrainedGridViewDescriptor; import org.jspresso.framework.view.descriptor.IEnumerationPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.IEvenGridViewDescriptor; import org.jspresso.framework.view.descriptor.IGridViewDescriptor; import org.jspresso.framework.view.descriptor.IHtmlViewDescriptor; import org.jspresso.framework.view.descriptor.IImageViewDescriptor; import org.jspresso.framework.view.descriptor.IListViewDescriptor; import org.jspresso.framework.view.descriptor.IMapViewDescriptor; import org.jspresso.framework.view.descriptor.INestedComponentPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.IPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.IReferencePropertyViewDescriptor; import org.jspresso.framework.view.descriptor.IRepeaterViewDescriptor; import org.jspresso.framework.view.descriptor.IScrollableViewDescriptor; import org.jspresso.framework.view.descriptor.ISimpleTreeLevelDescriptor; import org.jspresso.framework.view.descriptor.ISplitViewDescriptor; import org.jspresso.framework.view.descriptor.IStaticTextViewDescriptor; import org.jspresso.framework.view.descriptor.ITabViewDescriptor; import org.jspresso.framework.view.descriptor.ITableViewDescriptor; import org.jspresso.framework.view.descriptor.ITreeLevelDescriptor; import org.jspresso.framework.view.descriptor.ITreeViewDescriptor; import org.jspresso.framework.view.descriptor.IViewDescriptor; import org.jspresso.framework.view.descriptor.basic.BasicDatePropertyViewDescriptor; import org.jspresso.framework.view.descriptor.basic.BasicListViewDescriptor; import org.jspresso.framework.view.descriptor.basic.BasicNumberPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.basic.BasicPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.basic.BasicTableViewDescriptor; import org.jspresso.framework.view.descriptor.basic.BasicTimePropertyViewDescriptor; import org.jspresso.framework.view.descriptor.basic.PropertyViewDescriptorHelper; /** * Abstract base class factory for views. * * @param <E> * the actual gui component type used. * @param <F> * the actual icon type used. * @param <G> * the actual action type used. * @author Vincent Vandenschrick */ @SuppressWarnings("UnusedParameters") public abstract class AbstractViewFactory<E, F, G> implements IViewFactory<E, F, G> { /** * {@code BOLD_FONT}. */ protected static final String BOLD_FONT = ";BOLD;"; /** * {@code DEF_DISP_MAX_VALUE}. */ protected static final double DEF_DISP_MAX_VALUE = 1000; /** * {@code DEF_DISP_TEMPLATE_PERCENT}. */ protected static final double DEF_DISP_TEMPLATE_PERCENT = 99; /** * {@code TEMPLATE_CHAR}. */ protected static final char TEMPLATE_CHAR = 'O'; /** * {@code TEMPLATE_DATE}. */ protected static final Date TEMPLATE_DATE = new Date(27166271000L); /** * {@code TEMPLATE_DURATION}. */ protected static final Long TEMPLATE_DURATION = (long) (EDuration.ONE_SECOND.getMillis() + EDuration.ONE_MINUTE.getMillis() + EDuration.ONE_HOUR.getMillis() + EDuration.ONE_DAY.getMillis() + EDuration.ONE_WEEK.getMillis()); /** * {@code TEMPLATE_TIME}. */ protected static final Date TEMPLATE_TIME = new Date(366000); private IActionFactory<G, E> actionFactory; private IDisplayableAction binaryPropertyInfoAction; private IConfigurableConnectorFactory connectorFactory; private ERenderingOptions defaultActionMapRenderingOptions = ERenderingOptions.ICON; private ERenderingOptions defaultTabRenderingOptions = ERenderingOptions.LABEL_ICON; private boolean defaultHideActionWhenDisabled = false; private final IValueChangeListener firstRowSelector; private IIconFactory<F> iconFactory; private IComponentCollectionFactory componentCollectionFactory; private IDisplayableAction lovAction; private IDisplayableAction componentsLovActionTemplate; private int maxCharacterLength = 32; private int maxColumnCharacterLength = 32; private IModelCascadingBinder modelCascadingBinder; private IModelConnectorFactory modelConnectorFactory; private IMvcBinder mvcBinder; private IDisplayableAction openFileAsBinaryPropertyAction; private IDisplayableAction resetPropertyAction; private IDisplayableAction saveBinaryPropertyAsFileAction; private String formLabelMandatoryPropertyColorHex = "0xFFFF0000"; private String tableHeaderMandatoryPropertyColorHex = null; private boolean liveDebugUI = false; /** * Constructs a new {@code AbstractViewFactory} instance. */ protected AbstractViewFactory() { firstRowSelector = new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { if (evt.getNewValue() != null && !((Collection<?>) evt.getNewValue()).isEmpty()) { ((ICollectionConnector) evt.getSource()).setSelectedIndices(0); } } }; } /** * {@inheritDoc} */ @SuppressWarnings("ConstantConditions") @Override public IView<E> createView(IViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { try { actionHandler.pushToSecurityContext(viewDescriptor); IView<E> view = createCustomView(viewDescriptor, actionHandler, locale); if (view == null) { if (viewDescriptor instanceof IComponentViewDescriptor) { view = createComponentView((IComponentViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof IActionViewDescriptor) { view = createActionView((IActionViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof IPropertyViewDescriptor) { view = createPropertyView((IPropertyViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof ICollectionViewDescriptor) { view = createCollectionView((ICollectionViewDescriptor) viewDescriptor, actionHandler, locale); finishCollectionViewConfiguration(view, (ICollectionViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof ICardViewDescriptor) { view = createCardView((ICardViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof ITreeViewDescriptor) { view = createTreeView((ITreeViewDescriptor) viewDescriptor, actionHandler, locale); if (((ITreeViewDescriptor) viewDescriptor).getItemSelectionAction() != null) { ((IItemSelectable) view.getConnector()).addItemSelectionListener( new ConnectorActionAdapter<>(((ITreeViewDescriptor) viewDescriptor).getItemSelectionAction(), getActionFactory(), actionHandler, view)); } } else if (viewDescriptor instanceof IMapViewDescriptor) { view = createMapView((IMapViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof ICompositeViewDescriptor) { view = createCompositeView((ICompositeViewDescriptor) viewDescriptor, actionHandler, locale); } } if (view != null) { view.getConnector().setSecurityHandler(actionHandler); boolean locallyWritable = !viewDescriptor.isReadOnly(); if (locallyWritable) { try { actionHandler.pushToSecurityContext(EAuthorization.ENABLED); locallyWritable = actionHandler.isAccessGranted(viewDescriptor); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } view.getConnector().setLocallyWritable(locallyWritable); if (viewDescriptor.getReadabilityGates() != null) { for (IGate gate : viewDescriptor.getReadabilityGates()) { if (!(gate instanceof ISecurable) || actionHandler.isAccessGranted((ISecurable) gate)) { IGate clonedGate = gate.clone(); if (clonedGate instanceof IActionHandlerAware) { ((IActionHandlerAware) clonedGate).setActionHandler(actionHandler); } view.getConnector().addReadabilityGate(clonedGate); } } } if (viewDescriptor.getWritabilityGates() != null) { for (IGate gate : viewDescriptor.getWritabilityGates()) { if (!(gate instanceof ISecurable) || actionHandler.isAccessGranted((ISecurable) gate)) { IGate clonedGate = gate.clone(); if (clonedGate instanceof IActionHandlerAware) { ((IActionHandlerAware) clonedGate).setActionHandler(actionHandler); } view.getConnector().addWritabilityGate(clonedGate); } } } finishComponentConfiguration(viewDescriptor, actionHandler, locale, view); decorateWithActions(viewDescriptor, actionHandler, locale, view); decorateWithBorder(view, actionHandler, locale); view.getConnector().setModelDescriptor(viewDescriptor.getModelDescriptor()); if (!actionHandler.isAccessGranted(viewDescriptor)) { view.setPeer(createSecurityComponent()); } applyPreferredSize(view.getPeer(), viewDescriptor.getPreferredSize()); } else { view = createEmptyView(viewDescriptor, actionHandler, locale); } return view; } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } /** * Creates a and binds a collection pagination view. * * @param paginationViewDescriptor * the pagination view descriptor. * @param view * the view to complete. * @param actionHandler * the action handler. * @param locale * the locale. * @return the ready to assemble pagination view. */ protected IView<E> createPaginationView(IViewDescriptor paginationViewDescriptor, IView<E> view, IActionHandler actionHandler, Locale locale) { final IView<E> paginationView = createView(paginationViewDescriptor, actionHandler, locale); (view.getConnector()).addPropertyChangeListener(IValueConnector.MODEL_CONNECTOR_PROPERTY, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getNewValue() != null) { getMvcBinder().bind(paginationView.getConnector(), ((IValueConnector) evt.getNewValue()).getParentConnector()); } else { getMvcBinder().bind(paginationView.getConnector(), null); } } }); return paginationView; } /** * Gets the actionFactory. * * @return the actionFactory. */ @Override public IActionFactory<G, E> getActionFactory() { return actionFactory; } /** * Gets the connectorFactory. * * @return the connectorFactory. */ @Override public IConfigurableConnectorFactory getConnectorFactory() { return connectorFactory; } /** * Gets the iconFactory. * * @return the iconFactory. */ @Override public IIconFactory<F> getIconFactory() { return iconFactory; } /** * Sets the actionFactory. * * @param actionFactory * the actionFactory to set. */ public void setActionFactory(IActionFactory<G, E> actionFactory) { this.actionFactory = actionFactory; } /** * Sets the binaryPropertyInfoAction. * * @param binaryPropertyInfoAction * the binaryPropertyInfoAction to set. */ public void setBinaryPropertyInfoAction(IDisplayableAction binaryPropertyInfoAction) { this.binaryPropertyInfoAction = binaryPropertyInfoAction; } /** * Sets the connectorFactory. * * @param connectorFactory * the connectorFactory to set. */ public void setConnectorFactory(IConfigurableConnectorFactory connectorFactory) { this.connectorFactory = connectorFactory; } /** * Sets the defaultActionMapRenderingOptions. * * @param defaultActionMapRenderingOptions * the defaultActionMapRenderingOptions to set. */ public void setDefaultActionMapRenderingOptions(ERenderingOptions defaultActionMapRenderingOptions) { this.defaultActionMapRenderingOptions = defaultActionMapRenderingOptions; } /** * Sets default tab rendering options. * * @param defaultTabRenderingOptions * the default tab rendering options */ public void setDefaultTabRenderingOptions(ERenderingOptions defaultTabRenderingOptions) { this.defaultTabRenderingOptions = defaultTabRenderingOptions; } /** * Sets the iconFactory. * * @param iconFactory * the iconFactory to set. */ public void setIconFactory(IIconFactory<F> iconFactory) { this.iconFactory = iconFactory; } /** * Sets the lovAction. * * @param lovAction * the lovAction to set. */ public void setLovAction(IDisplayableAction lovAction) { this.lovAction = lovAction; } /** * Sets components lov action template. * * @param componentsLovActionTemplate * the components lov action template */ public void setComponentsLovActionTemplate(IDisplayableAction componentsLovActionTemplate) { this.componentsLovActionTemplate = componentsLovActionTemplate; } /** * Sets the maxCharacterLength. * * @param maxCharacterLength * the maxCharacterLength to set. */ public void setMaxCharacterLength(int maxCharacterLength) { this.maxCharacterLength = maxCharacterLength; } /** * Sets the maxColumnCharacterLength. * * @param maxColumnCharacterLength * the maxColumnCharacterLength to set. */ public void setMaxColumnCharacterLength(int maxColumnCharacterLength) { this.maxColumnCharacterLength = maxColumnCharacterLength; } /** * Sets the modelCascadingBinder. * * @param modelCascadingBinder * the modelCascadingBinder to set. */ public void setModelCascadingBinder(IModelCascadingBinder modelCascadingBinder) { this.modelCascadingBinder = modelCascadingBinder; } /** * Sets the modelConnectorFactory. * * @param modelConnectorFactory * the modelConnectorFactory to set. */ public void setModelConnectorFactory(IModelConnectorFactory modelConnectorFactory) { this.modelConnectorFactory = modelConnectorFactory; } /** * Sets the mvcBinder. * * @param mvcBinder * the mvcBinder to set. */ public void setMvcBinder(IMvcBinder mvcBinder) { this.mvcBinder = mvcBinder; } /** * Sets the openFileAsBinaryPropertyAction. * * @param openFileAsBinaryPropertyAction * the openFileAsBinaryPropertyAction to set. */ public void setOpenFileAsBinaryPropertyAction(IDisplayableAction openFileAsBinaryPropertyAction) { this.openFileAsBinaryPropertyAction = openFileAsBinaryPropertyAction; } /** * Sets the resetPropertyAction. * * @param resetPropertyAction * the resetPropertyAction to set. */ public void setResetPropertyAction(IDisplayableAction resetPropertyAction) { this.resetPropertyAction = resetPropertyAction; } /** * Sets the saveBinaryPropertyAsFileAction. * * @param saveBinaryPropertyAsFileAction * the saveBinaryPropertyAsFileAction to set. */ public void setSaveBinaryPropertyAsFileAction(IDisplayableAction saveBinaryPropertyAsFileAction) { this.saveBinaryPropertyAsFileAction = saveBinaryPropertyAsFileAction; } /** * Adds a card in a card view. * * @param cardView * the card view to add the card to. * @param card * the card to add. * @param cardName * the card name. */ protected abstract void addCard(IMapView<E> cardView, IView<E> card, String cardName); /** * Selects a child view in an indexed view, e.g. a tab view. * * @param viewComponent * the indexed view. * @param index * the child view index to select. */ protected abstract void selectChildViewIndex(E viewComponent, int index); /** * Applies a component preferred size. * * @param component * the component to apply the preferred sze on. * @param preferredSize * the preferred size to apply (might be null). */ protected abstract void applyPreferredSize(E component, Dimension preferredSize); /** * Selects the first element of a collection connector when its value changes. * * @param collectionConnector * the collection connector to attach the listener to. */ public void attachDefaultCollectionListener(ICollectionConnector collectionConnector) { collectionConnector.addValueChangeListener(firstRowSelector); } /** * Performs all the necessary connectors binding among the composite view and * its children. * * @param view * the composite view to bind. */ protected void bindCompositeView(ICompositeView<E> view) { if (view != null) { if (view.getDescriptor() instanceof ICompositeViewDescriptor) { ICompositeViewDescriptor viewDescriptor = (ICompositeViewDescriptor) view.getDescriptor(); if (viewDescriptor.isCascadingModels()) { IView<E> masterView = view.getChildren().get(0); IValueConnector viewConnector; if (masterView.getDescriptor().getModelDescriptor() instanceof IPropertyDescriptor) { IConfigurableCollectionConnectorProvider mainConnector = getConnectorFactory() .createConfigurableCollectionConnectorProvider(ModelRefPropertyConnector.THIS_PROPERTY, null); mainConnector.addChildConnector(masterView.getConnector().getId(), masterView.getConnector()); if (masterView.getConnector() instanceof ICollectionConnector) { mainConnector.setCollectionConnectorProvider((ICollectionConnector) masterView.getConnector()); } viewConnector = mainConnector; } else { ICompositeValueConnector mainConnector = getConnectorFactory().createCompositeValueConnector( ModelRefPropertyConnector.THIS_PROPERTY, null); mainConnector.addChildConnector(masterView.getConnector().getId(), masterView.getConnector()); viewConnector = mainConnector; } view.setConnector(viewConnector); for (int i = 1; i < view.getChildren().size(); i++) { IView<E> detailView = view.getChildren().get(i); IValueConnector detailConnector; if (detailView.getDescriptor().getModelDescriptor() instanceof IPropertyDescriptor) { IConfigurableCollectionConnectorProvider wrapper = getConnectorFactory() .createConfigurableCollectionConnectorProvider(ModelRefPropertyConnector.THIS_PROPERTY, null); wrapper.addChildConnector(detailView.getConnector().getId(), detailView.getConnector()); if (detailView.getConnector() instanceof ICollectionConnector) { wrapper.setCollectionConnectorProvider((ICollectionConnector) detailView.getConnector()); } detailConnector = wrapper; } else { detailConnector = detailView.getConnector(); } // We must dig into the composite structure to find the 1st non // composite view // to cascade the model while (masterView instanceof ICompositeView<?>) { masterView = ((ICompositeView<E>) masterView).getChildren().get(0); } getModelCascadingBinder().bind(masterView.getConnector(), detailConnector); masterView = detailView; } } else { String connectorId; IModelDescriptor modelDescriptor = viewDescriptor.getModelDescriptor(); if (modelDescriptor instanceof IPropertyDescriptor) { connectorId = modelDescriptor.getName(); } else { connectorId = ModelRefPropertyConnector.THIS_PROPERTY; } ICompositeValueConnector connector = getConnectorFactory().createCompositeValueConnector(connectorId, null); view.setConnector(connector); for (IView<E> childView : view.getChildren()) { connector.addChildConnector(childView.getConnector().getId(), childView.getConnector()); } } } } } /** * Computes a table column identifier that is used for sorting. * * @param viewDescriptor * the table view descriptor. * @param columnDescriptor * the column descriptor behind the column. * @return the column identifier. */ protected String computeColumnIdentifier(ITableViewDescriptor viewDescriptor, IPropertyViewDescriptor columnDescriptor) { IComponentDescriptor<?> rowDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor.getModelDescriptor()) .getCollectionDescriptor().getElementDescriptor(); String propertyName = columnDescriptor.getModelDescriptor().getName(); String identifier = propertyName; String renderedProperty = computeRenderedProperty(columnDescriptor); if (renderedProperty != null) { // for ref sorting to occur properly. identifier = identifier + "." + renderedProperty; } boolean sortable = columnDescriptor.isSortable(); if (sortable && PropertyViewDescriptorHelper.isComputed(rowDescriptor, propertyName)) { if (viewDescriptor.getPaginationViewDescriptor() != null) { // disable sort only if the table is not paginated sortable = rowDescriptor.getPropertyDescriptor(propertyName).getPersistenceFormula() != null; } } if (!sortable) { return "#" + identifier; } return identifier; } /** * Constructs a composite view. * * @param viewComponent * the peer view component * @param descriptor * the view descriptor * @return the created composite view. */ protected BasicCompositeView<E> constructCompositeView(E viewComponent, IViewDescriptor descriptor) { BasicCompositeView<E> view = new BasicCompositeView<>(viewComponent); view.setDescriptor(descriptor); return view; } /** * Creates an indexed view, e.g. for tab container. * * @param viewComponent * the view component peer. * @param descriptor * the view descriptor. * @return the created indexed view. */ protected BasicIndexedView<E> constructIndexedView(final E viewComponent, final ITabViewDescriptor descriptor) { BasicIndexedView<E> indexedView = new BasicIndexedView<E>(viewComponent) { @Override public void setConnector(IValueConnector connector) { super.setConnector(connector); if (descriptor.isLazy() && connector != null) { // Only keep the selected tab connector bound connector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { ICompositeValueConnector parentConnector = (AbstractCompositeValueConnector) getConnector(); for (IView<E> tabView : getChildren()) { IValueConnector tabViewConnector = tabView.getConnector(); if (tabViewConnector.getParentConnector() != null) { getMvcBinder().bind(tabViewConnector, null); parentConnector.removeChildConnector(tabViewConnector.getId()); tabViewConnector.setParentConnector(null); } } rebindTabViewIfNecessary(getChildView(getCurrentViewIndex())); } }); } } /** * {@inheritDoc} */ @Override public void setCurrentViewIndex(int index) { int oldIndex = getCurrentViewIndex(); if (index == oldIndex) { return; } super.setCurrentViewIndex(index); selectChildViewIndex(viewComponent, index); if (descriptor.isLazy()) { IView<E> oldSelectedView = getChildView(oldIndex); IView<E> newSelectedView = getChildView(index); if (newSelectedView != null && oldSelectedView != null) { rebindTabViewIfNecessary(newSelectedView); } } } private void rebindTabViewIfNecessary(IView<E> tabView) { IValueConnector childConnector = tabView.getConnector(); ICompositeValueConnector parentConnector = (AbstractCompositeValueConnector) getConnector(); if (parentConnector != null && childConnector != null && childConnector.getParentConnector() == null) { parentConnector.addChildConnector(childConnector.getId(), childConnector); if (parentConnector.getModelConnector() != null) { getMvcBinder().bind(childConnector, ((ICompositeValueConnector) parentConnector.getModelConnector()) .getChildConnector(childConnector.getId())); } else { getMvcBinder().bind(childConnector, null); } } } }; indexedView.setDescriptor(descriptor); return indexedView; } /** * Constructs a map view. * * @param viewComponent * the peer view component * @param descriptor * the view descriptor * @return the created map view. */ protected BasicMapView<E> constructMapView(E viewComponent, IViewDescriptor descriptor) { BasicMapView<E> view = new BasicMapView<>(viewComponent); view.setDescriptor(descriptor); return view; } /** * Constructs a view. * * @param viewComponent * the peer view component * @param descriptor * the view descriptor * @param connector * the view connector. * @return the created view. */ protected IView<E> constructView(E viewComponent, IViewDescriptor descriptor, IValueConnector connector) { BasicView<E> view = new BasicView<>(viewComponent); view.setConnector(connector); view.setDescriptor(descriptor); return view; } /** * Creates an action view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created action view. */ protected abstract IView<E> createActionView(IActionViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates the action list for a binary property (open from file, save as * file, reset, size info). * * @param propertyView * the view these actions will be triggered from. * @param actionHandler * the action handler. * @param locale * the locale. * @return the action list. */ protected List<G> createBinaryActions(IView<E> propertyView, IActionHandler actionHandler, Locale locale) { G openAction = getActionFactory().createAction(openFileAsBinaryPropertyAction, actionHandler, propertyView, locale); G saveAction = getActionFactory().createAction(saveBinaryPropertyAsFileAction, actionHandler, propertyView, locale); G resetAction = getActionFactory().createAction(resetPropertyAction, actionHandler, propertyView, locale); G infoAction = getActionFactory().createAction(binaryPropertyInfoAction, actionHandler, propertyView, locale); List<G> binaryActions = new ArrayList<>(); getActionFactory().setActionName(openAction, null); getActionFactory().setActionName(saveAction, null); getActionFactory().setActionName(resetAction, null); getActionFactory().setActionName(infoAction, null); binaryActions.add(openAction); binaryActions.add(saveAction); binaryActions.add(resetAction); binaryActions.add(infoAction); return binaryActions; } /** * Creates a binary property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createBinaryPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a boolean property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createBooleanPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a border view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler * @param locale * the locale. * @return the border view. */ protected abstract ICompositeView<E> createBorderView(IBorderViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a tree view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created tree view. */ protected abstract IView<E> createCardView(ICardViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a card view connector. * * @param cardView * the card view to create the connector for. * @param actionHandler * the action handler. * @param locale * the locale. * @return the card view connector. */ protected IValueConnector createCardViewConnector(final IMapView<E> cardView, final IActionHandler actionHandler, final Locale locale) { IValueConnector cardViewConnector = getConnectorFactory().createValueConnector( getConnectorIdForBeanView(cardView.getDescriptor())); cardViewConnector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { refreshCardView(cardView, false, actionHandler, locale); } }); return cardViewConnector; } /** * {@inheritDoc} */ @Override public void refreshCardView(IMapView<E> cardView, boolean unbindPrevious, IActionHandler actionHandler, Locale locale) { if (cardView != null) { IValueConnector cardViewConnector = cardView.getConnector(); Object cardModel = cardViewConnector.getConnectorValue(); E cardsPeer = cardView.getPeer(); IView<E> currentChildCardView = cardView.getCurrentView(); ICardViewDescriptor cardViewDescriptor = cardView.getDescriptor(); String cardName = cardViewDescriptor.getCardNameForModel(cardModel, actionHandler.getSubject()); if (cardName != null) { IView<E> childCardView = cardView.getChild(cardName); if (childCardView == null) { IViewDescriptor childCardViewDescriptor = cardViewDescriptor.getCardViewDescriptor(cardName); if (childCardViewDescriptor != null) { childCardView = createChildCardView(childCardViewDescriptor, actionHandler, locale); addCard(cardView, childCardView, cardName); } } if (childCardView != null) { cardView.setCurrentView(childCardView); IViewDescriptor childCardViewDescriptor = childCardView.getDescriptor(); boolean accessGranted = actionHandler.isAccessGranted(childCardViewDescriptor); if (cardModel instanceof ISecurable) { accessGranted = accessGranted && actionHandler.isAccessGranted((ISecurable) cardModel); } if (accessGranted) { showCardInPanel(cardsPeer, cardName); } else { // Do not unbind current connector for performance reason. if (unbindPrevious && currentChildCardView != null && currentChildCardView.getConnector() != null) { getMvcBinder().bind(currentChildCardView.getConnector(), null); } showCardInPanel(cardsPeer, ICardViewDescriptor.SECURITY_CARD); } IValueConnector childCardConnector = childCardView.getConnector(); if (childCardConnector != null) { // To handle polymorphism, especially for modules, we refine // the model descriptor. IValueConnector modelConnector = cardViewConnector.getModelConnector(); if (modelConnector != null && cardViewConnector.getModelDescriptor().getModelType().isAssignableFrom( childCardViewDescriptor.getModelDescriptor().getModelType())) { modelConnector.setModelDescriptor(childCardViewDescriptor.getModelDescriptor()); } if (unbindPrevious && currentChildCardView != null && currentChildCardView.getConnector() != null) { getMvcBinder().bind(currentChildCardView.getConnector(), null); } getMvcBinder().bind(childCardConnector, modelConnector); } } else { // Do not unbind current connector for performance reason. if (unbindPrevious && currentChildCardView != null && currentChildCardView.getConnector() != null) { getMvcBinder().bind(currentChildCardView.getConnector(), null); } showCardInPanel(cardsPeer, ICardViewDescriptor.DEFAULT_CARD); } } else { // Do not unbind current connector for performance reason. if (unbindPrevious && currentChildCardView != null && currentChildCardView.getConnector() != null) { getMvcBinder().bind(currentChildCardView.getConnector(), null); } showCardInPanel(cardsPeer, ICardViewDescriptor.DEFAULT_CARD); } } } /** * Create child card view view. * * @param childCardViewDescriptor * the child card view descriptor * @param actionHandler * the action handler * @param locale * the locale * @return the view */ protected IView<E> createChildCardView(IViewDescriptor childCardViewDescriptor, IActionHandler actionHandler, Locale locale) { return createView(childCardViewDescriptor, actionHandler, locale); } /** * Creates a color property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createColorPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Create nested component property view. * * @param propertyViewDescriptor * the property view descriptor * @param actionHandler * the action handler * @param locale * the locale * @return the view */ protected IView<E> createNestedComponentPropertyView(INestedComponentPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IViewDescriptor nestedComponentViewDescriptor = propertyViewDescriptor.getNestedComponentViewDescriptor(); IView<E> nestedComponentView = createView(nestedComponentViewDescriptor, actionHandler, locale); IRenderableCompositeValueConnector wrappingConnector = getConnectorFactory().createCompositeValueConnector( propertyViewDescriptor.getModelDescriptor().getName(), null); wrappingConnector.addChildConnector(ModelRefPropertyConnector.THIS_PROPERTY, nestedComponentView.getConnector()); wrappingConnector.setExceptionHandler(actionHandler); return constructView(nestedComponentView.getPeer(), propertyViewDescriptor, wrappingConnector); } /** * Creates a table column connector. * * @param columnViewDescriptor * the column descriptor to create the connector for. * @param descriptor * the component descriptor this table relies on. * @param actionHandler * the action handler. * @return the connector for the table column. */ protected IValueConnector createColumnConnector(IPropertyViewDescriptor columnViewDescriptor, IComponentDescriptor<?> descriptor, IActionHandler actionHandler) { String columnId = columnViewDescriptor.getModelDescriptor().getName(); IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) columnViewDescriptor.getModelDescriptor(); if (propertyDescriptor == null) { throw new ViewException("No property " + columnId + " defined for " + descriptor.getComponentContract()); } IValueConnector columnConnector; if (propertyDescriptor instanceof IReferencePropertyDescriptor<?>) { String renderedProperty = computeRenderedProperty(columnViewDescriptor); columnConnector = getConnectorFactory().createCompositeValueConnector(columnId, renderedProperty); } else { columnConnector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); } columnConnector.setSecurityHandler(actionHandler); boolean locallyWritable = !columnViewDescriptor.isReadOnly(); if (locallyWritable) { try { actionHandler.pushToSecurityContext(EAuthorization.ENABLED); locallyWritable = actionHandler.isAccessGranted(columnViewDescriptor); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } columnConnector.setLocallyWritable(locallyWritable); if (columnViewDescriptor.getReadabilityGates() != null) { for (IGate gate : columnViewDescriptor.getReadabilityGates()) { if (!(gate instanceof ISecurable) || actionHandler.isAccessGranted((ISecurable) gate)) { IGate clonedGate = gate.clone(); applyGateDependencyInjection(clonedGate, actionHandler); columnConnector.addReadabilityGate(clonedGate); } } } if (columnViewDescriptor.getWritabilityGates() != null) { for (IGate gate : columnViewDescriptor.getWritabilityGates()) { if (!(gate instanceof ISecurable) || actionHandler.isAccessGranted((ISecurable) gate)) { IGate clonedGate = gate.clone(); applyGateDependencyInjection(clonedGate, actionHandler); columnConnector.addWritabilityGate(clonedGate); } } } return columnConnector; } /** * Performs dependency injection on a gate. * * @param gate * the gate. * @param actionHandler * the action handler. */ protected void applyGateDependencyInjection(IGate gate, IActionHandler actionHandler) { if (gate instanceof ISecurityHandlerAware) { ((ISecurityHandlerAware) gate).setSecurityHandler(actionHandler); } if (gate instanceof IActionHandlerAware) { ((IActionHandlerAware) gate).setActionHandler(actionHandler); } if (gate instanceof ISubjectAware) { ((ISubjectAware) gate).setSubject(actionHandler.getSubject()); } } /** * Compute the rendered nested property of a reference property view * descriptor. * * @param propertyViewDescriptor * the property view descriptor. * @return the rendered property. */ protected String computeRenderedProperty(IPropertyViewDescriptor propertyViewDescriptor) { String renderedProperty = null; IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); if (propertyDescriptor instanceof IReferencePropertyDescriptor<?>) { List<String> renderedProperties = propertyViewDescriptor.getRenderedChildProperties(); if (renderedProperties != null && !renderedProperties.isEmpty()) { // it's a custom rendered property. renderedProperty = renderedProperties.get(0); } else { IComponentDescriptor<?> referencedDescriptor = ((IReferencePropertyDescriptor<?>) propertyDescriptor) .getReferencedDescriptor(); renderedProperty = referencedDescriptor.getToStringProperty(); } } return renderedProperty; } /** * Creates a component view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created component view. */ protected abstract IView<E> createComponentView(IComponentViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a map view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created component view. */ protected abstract IView<E> createMapView(IMapViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Computes the property name used to compute a property view dynamic label * or null if none or if the label is a static one. Note that for the label to be considered as a dynamic one, * the name must be different from the bound property name. * * @param modelDescriptor * the component model descriptor. * @param viewDescriptor * the view descriptor * @param propertyDescriptor * the property descriptor. * @return the property name used to compute a property view dynamic label * or null if none or if the label is a static one. */ protected String computePropertyDynamicLabel(IComponentDescriptor<?> modelDescriptor, IViewDescriptor viewDescriptor, IPropertyDescriptor propertyDescriptor) { String dynamicLabelProperty = null; String labelKey = null; if (viewDescriptor.getName() != null) { labelKey = viewDescriptor.getName(); } if (labelKey != null && !labelKey.equals(propertyDescriptor.getName())) { IPropertyDescriptor labelProperty = modelDescriptor.getPropertyDescriptor(labelKey); if (labelProperty != null) { dynamicLabelProperty = labelProperty.getName(); } } return dynamicLabelProperty; } /** * Computes the property name used to compute a property view dynamic tooltip * or null if none or if the tooltip is a static one. * * @param modelDescriptor * the component model descriptor. * @param viewDescriptor * the view descriptor * @param propertyDescriptor * the property descriptor. * @return the property name used to compute a property view dynamic tooltip * or null if none or if the tooltip is a static one. */ protected String computePropertyDynamicToolTip(IComponentDescriptor<?> modelDescriptor, IViewDescriptor viewDescriptor, IPropertyDescriptor propertyDescriptor) { String dynamicToolTipProperty = null; String descriptionKey = null; if (viewDescriptor.getDescription() != null) { descriptionKey = viewDescriptor.getDescription(); } else if (propertyDescriptor != null) { descriptionKey = propertyDescriptor.getDescription(); } if (descriptionKey != null) { IPropertyDescriptor descriptionProperty = modelDescriptor.getPropertyDescriptor(descriptionKey); if (descriptionProperty != null) { dynamicToolTipProperty = descriptionProperty.getName(); } } return dynamicToolTipProperty; } /** * Computes the property name used to compute a property view dynamic * background or null if none or if the background is a static one. * * @param modelDescriptor * the component model descriptor. * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the property descriptor. * @return the property name used to compute a property view dynamic * background or null if none or if the background is a static one. */ protected String computePropertyDynamicBackground(IComponentDescriptor<?> modelDescriptor, IPropertyViewDescriptor propertyViewDescriptor, IPropertyDescriptor propertyDescriptor) { String dynamicBackgroundProperty = null; String backgroundKey = null; if (propertyViewDescriptor.getBackground() != null) { backgroundKey = propertyViewDescriptor.getBackground(); } if (backgroundKey != null) { IPropertyDescriptor backgroundProperty = modelDescriptor.getPropertyDescriptor(backgroundKey); if (backgroundProperty != null) { dynamicBackgroundProperty = backgroundProperty.getName(); } } return dynamicBackgroundProperty; } /** * Computes the property name used to compute a property view dynamic * foreground or null if none or if the foreground is a static one. * * @param modelDescriptor * the component model descriptor. * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the property descriptor. * @return the property name used to compute a property view dynamic * foreground or null if none or if the foreground is a static one. */ protected String computePropertyDynamicForeground(IComponentDescriptor<?> modelDescriptor, IPropertyViewDescriptor propertyViewDescriptor, IPropertyDescriptor propertyDescriptor) { String dynamicForegroundProperty = null; String foregroundKey = null; if (propertyViewDescriptor.getForeground() != null) { foregroundKey = propertyViewDescriptor.getForeground(); } if (foregroundKey != null) { IPropertyDescriptor foregroundProperty = modelDescriptor.getPropertyDescriptor(foregroundKey); if (foregroundProperty != null) { dynamicForegroundProperty = foregroundProperty.getName(); } } return dynamicForegroundProperty; } /** * Computes the property name used to compute a property view dynamic font or * null if none or if the font is a static one. * * @param modelDescriptor * the component model descriptor. * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the property descriptor. * @return the property name used to compute a property view dynamic font or * null if none or if the font is a static one. */ protected String computePropertyDynamicFont(IComponentDescriptor<?> modelDescriptor, IPropertyViewDescriptor propertyViewDescriptor, IPropertyDescriptor propertyDescriptor) { String dynamicFontProperty = null; String fontKey = null; if (propertyViewDescriptor.getFont() != null) { fontKey = propertyViewDescriptor.getFont(); } if (fontKey != null) { IPropertyDescriptor fontProperty = modelDescriptor.getPropertyDescriptor(fontKey); if (fontProperty != null) { dynamicFontProperty = fontProperty.getName(); } } return dynamicFontProperty; } /** * Computes the property name used to compute a component view dynamic tooltip * or null if none or if the tooltip is a static one. * * @param viewDescriptor * the component view descriptor. * @param modelDescriptor * the model descriptor. * @return the property name used to compute a component view dynamic tooltip * or null if none or if the tooltip is a static one. */ protected String computeComponentDynamicToolTip(IViewDescriptor viewDescriptor, IComponentDescriptor<?> modelDescriptor) { String dynamicToolTipProperty = null; if (viewDescriptor.getDescription() != null) { IPropertyDescriptor descriptionProperty = modelDescriptor.getPropertyDescriptor(viewDescriptor.getDescription()); if (descriptionProperty != null) { dynamicToolTipProperty = descriptionProperty.getName(); } } else { dynamicToolTipProperty = modelDescriptor.getToHtmlProperty(); } return dynamicToolTipProperty; } /** * Computes the property name used to compute a component view background or * null if none or if the background is a static one. * * @param viewDescriptor * the component view descriptor. * @param modelDescriptor * the model descriptor. * @return the property name used to compute a component view dynamic * background or null if none or if the background is a static one. */ protected String computeComponentDynamicBackground(IViewDescriptor viewDescriptor, IComponentDescriptor<?> modelDescriptor) { String dynamicBackgroundProperty = null; if (viewDescriptor.getBackground() != null) { IPropertyDescriptor backgroundProperty = modelDescriptor.getPropertyDescriptor(viewDescriptor.getBackground()); if (backgroundProperty != null) { dynamicBackgroundProperty = backgroundProperty.getName(); } } return dynamicBackgroundProperty; } /** * Computes the property name used to compute a component view foreground or * null if none or if the foreground is a static one. * * @param viewDescriptor * the component view descriptor. * @param modelDescriptor * the model descriptor. * @return the property name used to compute a component view dynamic * foreground or null if none or if the foreground is a static one. */ protected String computeComponentDynamicForeground(IViewDescriptor viewDescriptor, IComponentDescriptor<?> modelDescriptor) { String dynamicForegroundProperty = null; if (viewDescriptor.getForeground() != null) { IPropertyDescriptor foregroundProperty = modelDescriptor.getPropertyDescriptor(viewDescriptor.getForeground()); if (foregroundProperty != null) { dynamicForegroundProperty = foregroundProperty.getName(); } } return dynamicForegroundProperty; } /** * Computes the property name used to compute a component view font or null if * none or if the font is a static one. * * @param viewDescriptor * the component view descriptor. * @param modelDescriptor * the model descriptor. * @return the property name used to compute a component view dynamic font or * null if none or if the font is a static one. */ protected String computeComponentDynamicFont(IViewDescriptor viewDescriptor, IComponentDescriptor<?> modelDescriptor) { String dynamicFontProperty = null; if (viewDescriptor.getFont() != null) { IPropertyDescriptor fontProperty = modelDescriptor.getPropertyDescriptor(viewDescriptor.getFont()); if (fontProperty != null) { dynamicFontProperty = fontProperty.getName(); } } return dynamicFontProperty; } /** * Creates a composite view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler * @param locale * the locale. * @return the composite view. */ protected ICompositeView<E> createCompositeView(ICompositeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { ICompositeView<E> view = null; if (viewDescriptor instanceof IBorderViewDescriptor) { view = createBorderView((IBorderViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof IGridViewDescriptor) { view = createGridView((IGridViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof ISplitViewDescriptor) { view = createSplitView((ISplitViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof ITabViewDescriptor) { view = createTabView((ITabViewDescriptor) viewDescriptor, actionHandler, locale); } bindCompositeView(view); if (view != null && viewDescriptor.isScrollable()) { view.setPeer(applyComponentScrollability(view.getPeer(), viewDescriptor)); } return view; } /** * Apply component scrollability. * * @param viewComponent * the viewComponent * @param viewDescriptor * the view descriptor * @return the scrollable container */ protected abstract E applyComponentScrollability(E viewComponent, IScrollableViewDescriptor viewDescriptor); /** * Creates a constrained grid view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the constrained grid view. */ protected abstract ICompositeView<E> createConstrainedGridView(IConstrainedGridViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Gives a chance to subclasses to create custom views. Returns null by * default. * * @param viewDescriptor * the view descriptor being the root of the view hierarchy to be * constructed. * @param actionHandler * the object responsible for executing the view actions (generally * the frontend controller itself). * @param locale * the locale the view must use for i18n. * @return the created view or null. */ protected IView<E> createCustomView(IViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { return null; } /** * Creates a number format based on a number property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the number property descriptor. * @param timeZone * the timezone. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the date format. */ protected SimpleDateFormat createDateFormat(IPropertyViewDescriptor propertyViewDescriptor, IDatePropertyDescriptor propertyDescriptor, TimeZone timeZone, ITranslationProvider translationProvider, Locale locale) { SimpleDateFormat format; String formatPattern; if (propertyViewDescriptor instanceof BasicDatePropertyViewDescriptor && ((BasicDatePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern() != null) { formatPattern = ((BasicDatePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern(); } else if (propertyDescriptor.getFormatPattern() != null) { formatPattern = propertyDescriptor.getFormatPattern(); } else { if (propertyDescriptor.getType() == EDateType.DATE) { formatPattern = getDatePattern(propertyDescriptor, translationProvider, locale); } else { formatPattern = getDatePattern(propertyDescriptor, translationProvider, locale) + " " + getTimePattern( propertyDescriptor, translationProvider, locale); } } format = new NullableSimpleDateFormat(formatPattern, locale); format.setTimeZone(timeZone); return format; } /** * Return the default date pattern expressed as a SimpleDateFormat pattern. * * @param propertyDescriptor * the date property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the default date pattern. */ protected String getDatePattern(IDatePropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return translationProvider.getDatePattern(locale); } /** * Return the default first day of week expressed as a day int (0 is sunday to 6 is saturday). * * @param propertyDescriptor * the date property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the default first day of week. */ protected int getFirstDayOfWeek(IDatePropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return translationProvider.getFirstDayOfWeek(locale); } /** * Return the default decimal separator. * * @param propertyDescriptor * the decimal property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the default decimal separator. */ protected String getDecimalSeparator(IDecimalPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return translationProvider.getDecimalSeparator(locale); } /** * Return the default thousands separator. * * @param propertyDescriptor * the number property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the default thousands separator. */ protected String getThousandsSeparator(INumberPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return translationProvider.getThousandsSeparator(locale); } /** * Return the default time pattern expressed as a SimpleDateFormat pattern. * * @param propertyDescriptor * the time aware property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the default date pattern. */ protected String getTimePattern(ITimeAwarePropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { if (propertyDescriptor.isMillisecondsAware()) { return translationProvider.getLongTimePattern(locale); } else if (propertyDescriptor.isSecondsAware()) { return translationProvider.getTimePattern(locale); } return translationProvider.getShortTimePattern(locale); } /** * Creates an enumeration formatter. * * @param propertyDescriptor * the enumeration property descriptor * @param translationProvider * the translation provider to use to translate the enumeration * values. * @param locale * the locale to create the formatter for. * @return the formatter. */ protected IFormatter<Object, String> createEnumerationFormatter(IEnumerationPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { Map<Object, String> translations = null; if (propertyDescriptor.isTranslated()) { translations = new HashMap<>(); for (String value : propertyDescriptor.getEnumerationValues()) { translations.put(value, propertyDescriptor.getI18nValue(value, translationProvider, locale)); } } IFormatter<Object, String> formatter = new EnumerationFormatter(translations); return formatter; } /** * Creates a date property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createDatePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a decimal format based on a decimal property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the decimal property descriptor * @param translationProvider * the translation provider * @param locale * the locale * @return the decimal format */ protected NumberFormat createDecimalFormat(IPropertyViewDescriptor propertyViewDescriptor, IDecimalPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { String formatPattern = getOverloadedPattern(propertyViewDescriptor, propertyDescriptor); DecimalFormat format = (DecimalFormat) NumberFormat.getNumberInstance(locale); applyDecimalFormatSymbols(format, propertyDescriptor, translationProvider, locale); if (formatPattern != null) { format.applyPattern(formatPattern); } else { format.setMaximumFractionDigits(propertyDescriptor.getMaxFractionDigit()); if (propertyDescriptor.isUsingBigDecimal()) { format.setParseBigDecimal(true); } format.setMinimumFractionDigits(format.getMaximumFractionDigits()); format.setGroupingUsed(propertyDescriptor.isThousandsGroupingUsed()); } return format; } private void applyDecimalFormatSymbols(DecimalFormat format, INumberPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { DecimalFormatSymbols symbols = format.getDecimalFormatSymbols(); if (propertyDescriptor instanceof IDecimalPropertyDescriptor) { String decimalSeparator = getDecimalSeparator((IDecimalPropertyDescriptor) propertyDescriptor, translationProvider, locale); if (decimalSeparator != null && decimalSeparator.length() > 0) { symbols.setDecimalSeparator(decimalSeparator.charAt(0)); } } String thousandsSeparator = getThousandsSeparator(propertyDescriptor, translationProvider, locale); if (thousandsSeparator != null && thousandsSeparator.length() > 0) { symbols.setGroupingSeparator(thousandsSeparator.charAt(0)); } else { format.setGroupingUsed(false); } format.setDecimalFormatSymbols(symbols); } /** * Creates a decimal formatter based on a decimal property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the decimal property descriptor * @param translationProvider * the translation provider * @param locale * the locale * @return the decimal formatter */ protected IFormatter<Object, String> createDecimalFormatter(IPropertyViewDescriptor propertyViewDescriptor, IDecimalPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new FormatAdapter( createDecimalFormat(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } /** * Creates a decimal property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createDecimalPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a duration formatter based on a duration property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the duration property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the duration formatter. */ protected IFormatter<Number, String> createDurationFormatter(IPropertyViewDescriptor propertyViewDescriptor, IDurationPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new DurationFormatter(translationProvider, locale, propertyDescriptor.isSecondsAware(), propertyDescriptor.isMillisecondsAware()); } /** * Creates a duration property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createDurationPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates an empty panel. * * @return the security panel. */ protected abstract E createEmptyComponent(); /** * Creates a date formatter based on a date property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the date property descriptor. * @param timeZone * the timezone. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the date formatter. */ protected IFormatter<?, String> createDateFormatter(IPropertyViewDescriptor propertyViewDescriptor, IDatePropertyDescriptor propertyDescriptor, TimeZone timeZone, ITranslationProvider translationProvider, Locale locale) { return createFormatter( createDateFormat(propertyViewDescriptor, propertyDescriptor, timeZone, translationProvider, locale)); } /** * Creates an enumeration property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createEnumerationPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates an evenly distributed grid view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the evenly distributed grid view. */ protected abstract ICompositeView<E> createEvenGridView(IEvenGridViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Wraps a format in a formatter. * * @param format * the format to wrap. * @return the resulting formatter. */ protected IFormatter<?, String> createFormatter(Format format) { return new FormatAdapter(format); } /** * Creates a formatter based on a property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the property descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the formatter. */ protected IFormatter<?, String> createFormatter(IPropertyViewDescriptor propertyViewDescriptor, IPropertyDescriptor propertyDescriptor, IActionHandler actionHandler, Locale locale) { if (propertyDescriptor instanceof IDatePropertyDescriptor) { TimeZone timeZone = ((IDatePropertyDescriptor) propertyDescriptor).isTimeZoneAware() ? actionHandler.getClientTimeZone() : actionHandler.getReferenceTimeZone(); return createDateFormatter(propertyViewDescriptor, (IDatePropertyDescriptor) propertyDescriptor, timeZone, actionHandler, locale); } if (propertyDescriptor instanceof ITimePropertyDescriptor) { return createTimeFormatter(propertyViewDescriptor, (ITimePropertyDescriptor) propertyDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof IDurationPropertyDescriptor) { return createDurationFormatter(propertyViewDescriptor, (IDurationPropertyDescriptor) propertyDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof IPercentPropertyDescriptor) { return createPercentFormatter(propertyViewDescriptor, (IPercentPropertyDescriptor) propertyDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof IDecimalPropertyDescriptor) { return createDecimalFormatter(propertyViewDescriptor, (IDecimalPropertyDescriptor) propertyDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof IIntegerPropertyDescriptor) { return createIntegerFormatter(propertyViewDescriptor, (IIntegerPropertyDescriptor) propertyDescriptor, actionHandler, locale); } return null; } /** * Creates a grid view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler * @param locale * the locale. * @return the grid view. */ protected ICompositeView<E> createGridView(IGridViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { ICompositeView<E> view = null; if (viewDescriptor instanceof IEvenGridViewDescriptor) { view = createEvenGridView((IEvenGridViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof IConstrainedGridViewDescriptor) { view = createConstrainedGridView((IConstrainedGridViewDescriptor) viewDescriptor, actionHandler, locale); } return view; } /** * Creates an html property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createHtmlPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a image property view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created image view. */ protected abstract IView<E> createImagePropertyView(IPropertyViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a static text property view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created static text view. */ protected abstract IView<E> createStaticTextPropertyView(IStaticTextViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates an integer format based on an integer property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the integer property descriptor * @param translationProvider * the translation provider * @param locale * the locale * @return the integer format */ protected NumberFormat createIntegerFormat(IPropertyViewDescriptor propertyViewDescriptor, IIntegerPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { String formatPattern = getOverloadedPattern(propertyViewDescriptor, propertyDescriptor); DecimalFormat format = (DecimalFormat) NumberFormat.getIntegerInstance(locale); applyDecimalFormatSymbols(format, propertyDescriptor, translationProvider, locale); if (formatPattern != null) { format.applyPattern(formatPattern); } else { format.setGroupingUsed(propertyDescriptor.isThousandsGroupingUsed()); } return format; } /** * Creates an integer formatter based on an integer property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the integer property descriptor * @param translationProvider * the translation provider * @param locale * the locale * @return the integer formatter */ protected IFormatter<Object, String> createIntegerFormatter(IPropertyViewDescriptor propertyViewDescriptor, IIntegerPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new FormatAdapter( createIntegerFormat(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } /** * Creates an integer property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createIntegerPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a list column connector. * * @param renderedProperty * the list rendered property. * @param descriptor * the component descriptor this list relies on. * @return the connector for the list. */ protected IValueConnector createListConnector(String renderedProperty, IComponentDescriptor<?> descriptor) { IPropertyDescriptor propertyDescriptor = descriptor.getPropertyDescriptor(renderedProperty); if (propertyDescriptor == null) { throw new ViewException("No property " + renderedProperty + " defined for " + descriptor.getComponentContract()); } if (propertyDescriptor instanceof IReferencePropertyDescriptor<?>) { return getConnectorFactory().createCompositeValueConnector(renderedProperty, ((IReferencePropertyDescriptor<?>) propertyDescriptor).getReferencedDescriptor().getToStringProperty()); } return getConnectorFactory().createValueConnector(propertyDescriptor.getName()); } /** * Creates a list view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created list view. */ protected abstract IView<E> createListView(IListViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates the list of value action. * * @param propertyView * the view these actions will be triggered from. * @param actionHandler * the action handler. * @param locale * the locale. * @return the generic list of value action. */ protected G createLovAction(IView<E> propertyView, IActionHandler actionHandler, Locale locale) { IPropertyViewDescriptor propertyViewDescriptor = (IPropertyViewDescriptor) propertyView.getDescriptor(); IDisplayableAction listOfValueAction; if (propertyViewDescriptor instanceof IReferencePropertyViewDescriptor && ((IReferencePropertyViewDescriptor) propertyViewDescriptor).getLovAction() != null) { listOfValueAction = ((IReferencePropertyViewDescriptor) propertyViewDescriptor).getLovAction(); } else { listOfValueAction = getLovAction(); } Collection<IGate> aGates = listOfValueAction.getActionabilityGates(); if (aGates != null) { aGates.remove(ModelTrackingGate.INSTANCE); } G action = getActionFactory().createAction(listOfValueAction, actionHandler, propertyView, locale); getActionFactory().setActionName(action, null); return action; } /** * Creates a number property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected IView<E> createNumberPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IView<E> view = null; INumberPropertyDescriptor propertyDescriptor = (INumberPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); if (propertyDescriptor instanceof IIntegerPropertyDescriptor) { view = createIntegerPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IDecimalPropertyDescriptor) { view = createDecimalPropertyView(propertyViewDescriptor, actionHandler, locale); } return view; } /** * Creates a password property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createPasswordPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Gets overloaded pattern. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the property descriptor * @return the overloaded pattern */ protected String getOverloadedPattern(IPropertyViewDescriptor propertyViewDescriptor, INumberPropertyDescriptor propertyDescriptor) { String formatPattern = null; if (propertyViewDescriptor instanceof BasicNumberPropertyViewDescriptor && ((BasicNumberPropertyViewDescriptor) propertyViewDescriptor).getFormatPattern() != null) { formatPattern = ((BasicNumberPropertyViewDescriptor) propertyViewDescriptor).getFormatPattern(); } else if (propertyDescriptor.getFormatPattern() != null) { formatPattern = propertyDescriptor.getFormatPattern(); } return formatPattern; } /** * Creates a percent format based on a percent property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the percent property descriptor * @param translationProvider * the translation provider * @param locale * the locale * @return the percent format */ protected NumberFormat createPercentFormat(IPropertyViewDescriptor propertyViewDescriptor, IPercentPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { String formatPattern = getOverloadedPattern(propertyViewDescriptor, propertyDescriptor); DecimalFormat format = (DecimalFormat) NumberFormat.getPercentInstance(locale); applyDecimalFormatSymbols(format, propertyDescriptor, translationProvider, locale); if (formatPattern != null) { format.applyPattern(formatPattern); } else { format.setMaximumFractionDigits(propertyDescriptor.getMaxFractionDigit()); if (propertyDescriptor.isUsingBigDecimal()) { format.setParseBigDecimal(true); } format.setMinimumFractionDigits(format.getMaximumFractionDigits()); format.setGroupingUsed(propertyDescriptor.isThousandsGroupingUsed()); } return format; } /** * Creates a percent formatter based on a percent property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the percent property descriptor * @param translationProvider * the translation provider * @param locale * the locale * @return the percent formatter */ protected IFormatter<Object, String> createPercentFormatter(IPropertyViewDescriptor propertyViewDescriptor, IPercentPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new FormatAdapter( createPercentFormat(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } /** * Creates a percent property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the evenly distributed grid view. */ protected abstract IView<E> createPercentPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a single property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected IView<E> createPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IView<E> view = null; IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); if (propertyViewDescriptor instanceof IImageViewDescriptor) { // First of all, test for Image property view before deciding based on the // model. view = createImagePropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyViewDescriptor instanceof IStaticTextViewDescriptor) { // Then, test for static text property view before deciding based on the // model. view = createStaticTextPropertyView((IStaticTextViewDescriptor) propertyViewDescriptor, actionHandler, locale); } else if (propertyViewDescriptor instanceof IHtmlViewDescriptor) { // Then, test for Html property view before deciding based on the // model. view = createHtmlPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyViewDescriptor instanceof INestedComponentPropertyViewDescriptor) { view = createNestedComponentPropertyView((INestedComponentPropertyViewDescriptor) propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IBooleanPropertyDescriptor) { view = createBooleanPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IDatePropertyDescriptor) { view = createDatePropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof ITimePropertyDescriptor) { view = createTimePropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IDurationPropertyDescriptor) { view = createDurationPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IEnumerationPropertyDescriptor) { view = createEnumerationPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof INumberPropertyDescriptor) { view = createNumberPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IRelationshipEndPropertyDescriptor) { view = createRelationshipEndPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IStringPropertyDescriptor) { view = createTextualPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IImageBinaryPropertyDescriptor) { view = createImagePropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IBinaryPropertyDescriptor) { view = createBinaryPropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IColorPropertyDescriptor) { view = createColorPropertyView(propertyViewDescriptor, actionHandler, locale); } if (view != null) { if (propertyViewDescriptor.getAction() != null && !propertyViewDescriptor.isReadOnly()) { // We must listen for incoming connector value change to trigger the // action. final IValueConnector viewConnector = view.getConnector(); if (viewConnector != null) { viewConnector.addValueChangeListener( new ConnectorActionAdapter<>(propertyViewDescriptor.getAction(), getActionFactory(), actionHandler, view)); } } } return view; } /** * Creates a reference property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createReferencePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a relationship end property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected IView<E> createRelationshipEndPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IView<E> view = null; IRelationshipEndPropertyDescriptor propertyDescriptor = (IRelationshipEndPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); if (propertyDescriptor instanceof IReferencePropertyDescriptor<?>) { view = createReferencePropertyView(propertyViewDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof ICollectionPropertyDescriptor<?>) { view = createCollectionPropertyView(propertyViewDescriptor, actionHandler, locale); } return view; } /** * Creates a panel to be substituted with any view when the user is not * granted access. * * @return the security panel. */ protected abstract E createSecurityComponent(); /** * Creates a source code property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createSourceCodePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a split view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler * @param locale * the locale. * @return the split view. */ protected abstract ICompositeView<E> createSplitView(ISplitViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a string property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createStringPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a table view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created table view. */ protected abstract IView<E> createTableView(ITableViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a repeater view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created table view. */ protected abstract IView<E> createRepeaterView(IRepeaterViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a tab view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler * @param locale * the locale. * @return the tab view. */ protected abstract ICompositeView<E> createTabView(ITabViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a text property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createTextPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a textual property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected IView<E> createTextualPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IStringPropertyDescriptor propertyDescriptor = (IStringPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); if (propertyDescriptor instanceof IPasswordPropertyDescriptor) { return createPasswordPropertyView(propertyViewDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof ISourceCodePropertyDescriptor) { return createSourceCodePropertyView(propertyViewDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof IHtmlPropertyDescriptor) { return createHtmlPropertyView(propertyViewDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof ITextPropertyDescriptor) { return createTextPropertyView(propertyViewDescriptor, actionHandler, locale); } if (propertyDescriptor instanceof IImageUrlPropertyDescriptor) { return createImagePropertyView(propertyViewDescriptor, actionHandler, locale); } return createStringPropertyView(propertyViewDescriptor, actionHandler, locale); } /** * Creates a time format based on a time property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the time property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the time format. */ protected SimpleDateFormat createTimeFormat(IPropertyViewDescriptor propertyViewDescriptor, ITimePropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { String formatPattern; if (propertyViewDescriptor instanceof BasicTimePropertyViewDescriptor && ((BasicTimePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern() != null) { formatPattern = ((BasicTimePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern(); } else if (propertyDescriptor.getFormatPattern() != null) { formatPattern = propertyDescriptor.getFormatPattern(); } else { formatPattern = getTimePattern(propertyDescriptor, translationProvider, locale); } SimpleDateFormat format = new NullableSimpleDateFormat(formatPattern, locale); return format; } /** * Creates a time formatter based on an time property descriptor. * * @param propertyViewDescriptor * the property view descriptor * @param propertyDescriptor * the time property descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the time formatter. */ protected IFormatter<?, String> createTimeFormatter(IPropertyViewDescriptor propertyViewDescriptor, ITimePropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return createFormatter(createTimeFormat(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } /** * Creates a time property view. * * @param propertyViewDescriptor * the property view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created property view. */ protected abstract IView<E> createTimePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates a tree view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created tree view. */ protected abstract IView<E> createTreeView(ITreeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale); /** * Creates the connector for a tree view. * * @param viewDescriptor * the tree view descriptor. * @param actionHandler * the action handler. * @param locale * the locale to use. * @return the connector for the tree view. */ protected ICompositeValueConnector createTreeViewConnector(ITreeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { ITreeLevelDescriptor rootDescriptor = viewDescriptor.getRootSubtreeDescriptor(); ICompositeValueConnector connector = null; if (rootDescriptor instanceof ICompositeTreeLevelDescriptor) { IConfigurableCollectionConnectorListProvider compositeConnector = connectorFactory .createConfigurableCollectionConnectorListProvider(ModelRefPropertyConnector.THIS_PROPERTY, rootDescriptor.getNodeGroupDescriptor().getRenderedProperty()); List<ICollectionConnectorProvider> subtreeConnectors = new ArrayList<>(); if (((ICompositeTreeLevelDescriptor) rootDescriptor).getChildrenDescriptors() != null) { for (ITreeLevelDescriptor subtreeViewDescriptor : ((ICompositeTreeLevelDescriptor) rootDescriptor) .getChildrenDescriptors()) { if (actionHandler.isAccessGranted(subtreeViewDescriptor)) { try { actionHandler.pushToSecurityContext(subtreeViewDescriptor); ICollectionConnectorProvider subtreeConnector = createNodeGroupConnector(viewDescriptor, actionHandler, locale, subtreeViewDescriptor, 1); compositeConnector.addChildConnector(subtreeConnector.getId(), subtreeConnector); subtreeConnectors.add(subtreeConnector); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } } compositeConnector.setCollectionConnectorProviders(subtreeConnectors); connector = compositeConnector; } else if (rootDescriptor instanceof ISimpleTreeLevelDescriptor) { IConfigurableCollectionConnectorProvider simpleConnector = connectorFactory .createConfigurableCollectionConnectorProvider(ModelRefPropertyConnector.THIS_PROPERTY, rootDescriptor.getNodeGroupDescriptor().getRenderedProperty()); ITreeLevelDescriptor childDescriptor = ((ISimpleTreeLevelDescriptor) rootDescriptor).getChildDescriptor(); if (childDescriptor != null) { if (actionHandler.isAccessGranted(childDescriptor)) { try { actionHandler.pushToSecurityContext(childDescriptor); ICollectionConnectorProvider subtreeConnector = createNodeGroupConnector(viewDescriptor, actionHandler, locale, childDescriptor, 1); simpleConnector.addChildConnector(subtreeConnector.getId(), subtreeConnector); simpleConnector.setCollectionConnectorProvider(subtreeConnector); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } connector = simpleConnector; } if (connector instanceof AbstractCompositeValueConnector) { ((AbstractCompositeValueConnector) connector).setDisplayValue(viewDescriptor.getI18nName(actionHandler, locale)); ((AbstractCompositeValueConnector) connector).setDisplayDescription( viewDescriptor.getI18nDescription(actionHandler, locale)); ((AbstractCompositeValueConnector) connector).setDisplayIcon(viewDescriptor.getIcon()); ((AbstractCompositeValueConnector) connector).setIconImageURLProvider(viewDescriptor.getIconImageURLProvider()); } //noinspection ConstantConditions if (connector instanceof ICollectionConnectorListProvider) { ((ICollectionConnectorListProvider) connector).setTracksChildrenSelection(true); } if (connector instanceof IItemSelectable && connector instanceof ICollectionConnectorProvider) { final IItemSelectable rootConnector = ((IItemSelectable) connector); rootConnector.addItemSelectionListener(new IItemSelectionListener() { @Override public void selectedItemChange(ItemSelectionEvent event) { if (event.getSelectedItem() == null) { // change selected item so that the root connector is considered // selected. event.setSelectedItem(rootConnector); } } }); } return connector; } /** * Decorates a view with the actions registered in the view descriptor. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @param view * the raw view. */ protected abstract void decorateWithActions(IViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale, IView<E> view); /** * Decorates a view with a border. * * @param view * the view to decorate. * @param translationProvider * the translation provider. * @param locale * the locale to be used for a titled border. */ protected abstract void decorateWithBorder(IView<E> view, ITranslationProvider translationProvider, Locale locale); /** * Applies the font and color configuration to a view. * * @param viewDescriptor * the view descriptor. * @param translationProvider * the translation provider. * @param locale * the locale. * @param view * the raw view. */ protected abstract void finishComponentConfiguration(IViewDescriptor viewDescriptor, ITranslationProvider translationProvider, Locale locale, IView<E> view); /** * Computes the connector id for component view. * * @param viewDescriptor * the component view descriptor. * @return the computed connector id. * * @deprecated use more generic getConnectorIdForBeanView instead. */ @Deprecated protected String getConnectorIdForComponentView(IComponentViewDescriptor viewDescriptor) { return getConnectorIdForBeanView(viewDescriptor); } /** * Computes the connector id for bean based view. * * @param viewDescriptor * the component view descriptor. * @return the computed connector id. */ protected String getConnectorIdForBeanView(IViewDescriptor viewDescriptor) { if (viewDescriptor.getModelDescriptor() == null || viewDescriptor .getModelDescriptor() instanceof IComponentDescriptor<?>) { return ModelRefPropertyConnector.THIS_PROPERTY; } return viewDescriptor.getModelDescriptor().getName(); } /** * Gets a date template value. * * @param propertyDescriptor * the property descriptor. * @return the date template value. */ protected Date getDateTemplateValue(IDatePropertyDescriptor propertyDescriptor) { return TEMPLATE_DATE; } /** * Gets a decimal template value. * * @param propertyDescriptor * the property descriptor. * @return the decimal template value. */ protected Double getDecimalTemplateValue(IDecimalPropertyDescriptor propertyDescriptor) { double templateValue = DEF_DISP_MAX_VALUE; if (propertyDescriptor.getMaxValue() != null) { templateValue = propertyDescriptor.getMaxValue().doubleValue(); } int maxFractionDigit = propertyDescriptor.getMaxFractionDigit(); double decimalPart = 0; for (int i = 1; i <= maxFractionDigit; i++) { decimalPart += Math.pow(10.0D, -i); } templateValue += decimalPart; return templateValue; } /** * Gets the defaultActionMapRenderingOptions. * * @return the defaultActionMapRenderingOptions. */ protected ERenderingOptions getDefaultActionMapRenderingOptions() { return defaultActionMapRenderingOptions; } /** * Gets default tab rendering options. * * @return the default tab rendering options */ protected ERenderingOptions getDefaultTabRenderingOptions() { return defaultTabRenderingOptions; } /** * Gets a duration template value. * * @param propertyDescriptor * the property descriptor. * @return the duration template value. */ protected Long getDurationTemplateValue(IDurationPropertyDescriptor propertyDescriptor) { return TEMPLATE_DURATION; } /** * Gets an enumeration template value. * * @param propertyDescriptor * the property descriptor. * @param translationProvider * the translation provider to use to translate the enumeration * values. * @param locale * the locale. * @return the enumeration template value. */ protected String getEnumerationTemplateValue(IEnumerationPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { int maxTranslationLength = -1; if (translationProvider != null && propertyDescriptor.isTranslated()) { for (String enumerationValue : propertyDescriptor.getEnumerationValues()) { String translation = propertyDescriptor.getI18nValue(enumerationValue, translationProvider, locale); if (translation.length() > maxTranslationLength) { maxTranslationLength = translation.length(); } } } else { maxTranslationLength = propertyDescriptor.getMaxLength(); } if (maxTranslationLength == -1 || maxTranslationLength > getMaxCharacterLength()) { maxTranslationLength = getMaxCharacterLength(); } return getStringTemplateValue(maxTranslationLength); } /** * Computes the number of characters used to represent a template value based * on a formatter. * * @param formatter * the formatter. * @param templateValue * the template value. * @return the number of characters used to represent the template value. */ @SuppressWarnings("unchecked") protected int getFormatLength(IFormatter<?, String> formatter, Object templateValue) { int formatLength; if (formatter != null) { formatLength = ((IFormatter<Object, String>) formatter).format(templateValue).length(); } else { if (templateValue != null) { formatLength = templateValue.toString().length(); } else { formatLength = getMaxCharacterLength(); } } return formatLength; } /** * Gets an integer template value. * * @param propertyDescriptor * the property descriptor. * @return the integer template value. */ protected Integer getIntegerTemplateValue(IIntegerPropertyDescriptor propertyDescriptor) { double templateValue = DEF_DISP_MAX_VALUE; if (propertyDescriptor.getMaxValue() != null) { templateValue = propertyDescriptor.getMaxValue().doubleValue(); } return (int) templateValue; } /** * Gets the lovAction. * * @return the lovAction. */ protected IDisplayableAction getLovAction() { return lovAction; } /** * Gets components lov action template. * * @return the components lov action template */ public IDisplayableAction getComponentsLovActionTemplate() { return componentsLovActionTemplate; } /** * Gets the maxCharacterLength. * * @return the maxCharacterLength. */ protected int getMaxCharacterLength() { return maxCharacterLength; } /** * Gets the maxColumnCharacterLength. * * @return the maxColumnCharacterLength. */ protected int getMaxColumnCharacterLength() { return maxColumnCharacterLength; } /** * Gets the modelCascadingBinder. * * @return the modelCascadingBinder. */ protected IModelCascadingBinder getModelCascadingBinder() { return modelCascadingBinder; } /** * Gets the modelConnectorFactory. * * @return the modelConnectorFactory. */ protected IModelConnectorFactory getModelConnectorFactory() { return modelConnectorFactory; } /** * Gets the mvcBinder. * * @return the mvcBinder. */ public IMvcBinder getMvcBinder() { return mvcBinder; } /** * Gets an percent template value. * * @param propertyDescriptor * the property descriptor. * @return the percent template value. */ protected Double getPercentTemplateValue(IPercentPropertyDescriptor propertyDescriptor) { double templateValue = DEF_DISP_TEMPLATE_PERCENT; if (propertyDescriptor.getMaxValue() != null) { templateValue = propertyDescriptor.getMaxValue().doubleValue(); } int maxFractionDigit = propertyDescriptor.getMaxFractionDigit(); double decimalPart = 0; for (int i = 1; i <= maxFractionDigit; i++) { decimalPart += Math.pow(10.0D, -i); } templateValue += decimalPart; return templateValue / 100.0D; } /** * Gets an string template value. * * @param maxLength * the attribute max length. * @return the string template value. */ protected String getStringTemplateValue(Integer maxLength) { StringBuilder templateValue = new StringBuilder(); int fieldLength = getMaxCharacterLength(); if (maxLength != null) { fieldLength = maxLength; } for (int i = 0; i < fieldLength; i++) { templateValue.append(TEMPLATE_CHAR); } return templateValue.toString(); } /** * Gets an string template value. * * @param propertyDescriptor * the property descriptor. * @return the string template value. */ protected String getStringTemplateValue(IStringPropertyDescriptor propertyDescriptor) { return getStringTemplateValue(propertyDescriptor.getMaxLength()); } /** * Gets a template value matching a property descriptor. This is useful for * computing preferred width on components. * * @param propertyDescriptor * the property descriptor. * @return a field template value. */ protected Object getTemplateValue(IPropertyDescriptor propertyDescriptor) { if (propertyDescriptor instanceof IDatePropertyDescriptor) { return getDateTemplateValue((IDatePropertyDescriptor) propertyDescriptor); } if (propertyDescriptor instanceof ITimePropertyDescriptor) { return getTimeTemplateValue((ITimePropertyDescriptor) propertyDescriptor); } if (propertyDescriptor instanceof IDurationPropertyDescriptor) { return getDurationTemplateValue((IDurationPropertyDescriptor) propertyDescriptor); } if (propertyDescriptor instanceof IStringPropertyDescriptor) { return getStringTemplateValue((IStringPropertyDescriptor) propertyDescriptor); } if (propertyDescriptor instanceof IPercentPropertyDescriptor) { return getPercentTemplateValue((IPercentPropertyDescriptor) propertyDescriptor); } if (propertyDescriptor instanceof IDecimalPropertyDescriptor) { return getDecimalTemplateValue((IDecimalPropertyDescriptor) propertyDescriptor); } if (propertyDescriptor instanceof IIntegerPropertyDescriptor) { return getIntegerTemplateValue((IIntegerPropertyDescriptor) propertyDescriptor); } if (propertyDescriptor instanceof IReferencePropertyDescriptor<?>) { return getTemplateValue(((IReferencePropertyDescriptor<?>) propertyDescriptor).getReferencedDescriptor() .getPropertyDescriptor( ((IReferencePropertyDescriptor<?>) propertyDescriptor) .getReferencedDescriptor() .getToStringProperty())); } return null; } /** * Gets a time template value. * * @param propertyDescriptor * the property descriptor. * @return the time template value. */ protected Date getTimeTemplateValue(ITimePropertyDescriptor propertyDescriptor) { return TEMPLATE_TIME; } /** * Gets whether a property view is considered to fill all the available height * space. * * @param propertyViewDescriptor * the property view descriptor. * @return true if a property view is considered to fill all the available * height space. */ protected boolean isHeightExtensible(IPropertyViewDescriptor propertyViewDescriptor) { if (propertyViewDescriptor.getPreferredSize() == null || propertyViewDescriptor.getPreferredSize().getHeight() <= 0) { IModelDescriptor propertyDescriptor = propertyViewDescriptor.getModelDescriptor(); if (propertyDescriptor instanceof ITextPropertyDescriptor || propertyDescriptor instanceof ICollectionPropertyDescriptor<?>) { return true; } if (propertyViewDescriptor instanceof IStaticTextViewDescriptor && ((IStaticTextViewDescriptor) propertyViewDescriptor).isMultiLine()) { return true; } } return false; } /** * Shows a card in in card laid out panel. * * @param cardsPeer * the component that holds the cards * @param cardName * the card identifier to show. */ protected abstract void showCardInPanel(E cardsPeer, String cardName); private IView<E> createCollectionPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IView<E> view; ICollectionPropertyDescriptor<?> propertyDescriptor = (ICollectionPropertyDescriptor<?>) propertyViewDescriptor .getModelDescriptor(); List<String> renderedChildProperties = propertyViewDescriptor.getRenderedChildProperties(); if (renderedChildProperties == null) { renderedChildProperties = propertyViewDescriptor.getDefaultRenderedChildProperties(); } if (renderedChildProperties != null && renderedChildProperties.size() > 1) { BasicTableViewDescriptor viewDescriptor = new BasicTableViewDescriptor(); viewDescriptor.setModelDescriptor(propertyDescriptor); List<IPropertyViewDescriptor> columnViewDescriptors = new ArrayList<>(); for (String renderedProperty : renderedChildProperties) { BasicPropertyViewDescriptor columnDescriptor = new BasicPropertyViewDescriptor(); columnDescriptor.setName(renderedProperty); columnViewDescriptors.add(columnDescriptor); } viewDescriptor.setColumnViewDescriptors(columnViewDescriptors); viewDescriptor.setName(propertyDescriptor.getName()); viewDescriptor.setPreferredSize(propertyViewDescriptor.getPreferredSize()); view = createTableView(viewDescriptor, actionHandler, locale); } else { BasicListViewDescriptor viewDescriptor = new BasicListViewDescriptor(); viewDescriptor.setModelDescriptor(propertyDescriptor); if (renderedChildProperties != null && renderedChildProperties.size() == 1) { viewDescriptor.setRenderedProperty(renderedChildProperties.get(0)); } viewDescriptor.setName(propertyDescriptor.getName()); viewDescriptor.setPreferredSize(propertyViewDescriptor.getPreferredSize()); view = createListView(viewDescriptor, actionHandler, locale); } if (view instanceof BasicView) { ((BasicView<E>) view).setDescriptor(propertyViewDescriptor); } return view; } /** * Creates a collection view. * * @param viewDescriptor * the view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. * @return the created collection view. */ protected IView<E> createCollectionView(ICollectionViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { IView<E> view = null; if (viewDescriptor instanceof IListViewDescriptor) { view = createListView((IListViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof ITableViewDescriptor) { view = createTableView((ITableViewDescriptor) viewDescriptor, actionHandler, locale); } else if (viewDescriptor instanceof IRepeaterViewDescriptor) { view = createRepeaterView((IRepeaterViewDescriptor) viewDescriptor, actionHandler, locale); } return view; } private void bindSelectionConnector(final ICollectionConnectorProvider viewConnector, final ICollectionConnector viewSelectionConnector) { viewSelectionConnector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { viewConnector.setSelectedIndices( ConnectorHelper.getIndicesOf(viewConnector.getCollectionConnector(), (Collection<?>) evt.getNewValue())); } }); viewConnector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { viewConnector.setSelectedIndices(ConnectorHelper.getIndicesOf(viewConnector.getCollectionConnector(), (Collection<?>) viewSelectionConnector.getConnectorValue())); } }); viewSelectionConnector.addPropertyChangeListener(IValueConnector.MODEL_CONNECTOR_PROPERTY, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { IValueConnector oldModelConnector = (IValueConnector) evt.getOldValue(); if (oldModelConnector != null) { oldModelConnector.setConnectorValue(null); } } }); viewConnector.addSelectionChangeListener(new ISelectionChangeListener() { @Override public void selectionChange(SelectionChangeEvent evt) { int[] selectedIndices = evt.getNewSelection(); Collection<?> elements = viewConnector.getConnectorValue(); Collection<Object> selectedElements = null; if (selectedIndices != null && selectedIndices.length > 0 && elements != null && elements.size() > 0) { selectedElements = getComponentCollectionFactory().createComponentCollection( ((ICollectionDescriptorProvider<?>) viewSelectionConnector.getModelDescriptor()).getCollectionDescriptor() .getCollectionInterface ()); List<?> elementsList = new ArrayList<Object>(elements); for (int iselectedIndex : selectedIndices) { if (iselectedIndex >= 0 && iselectedIndex < elementsList.size()) { selectedElements.add(elementsList.get(iselectedIndex)); } } } viewSelectionConnector.setConnectorValue(selectedElements); } }); } /** * Binds the item selection action and decorates with the pagination view. * * @param view * the collection view to configure. * @param viewDescriptor * the collection view descriptor. * @param actionHandler * the action handler. * @param locale * the locale. */ public void finishCollectionViewConfiguration(IView<E> view, ICollectionViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { if (view != null) { if (viewDescriptor.getSelectionModelDescriptor() != null) { ICollectionDescriptorProvider<?> selectionModelDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor .getSelectionModelDescriptor()); IComponentDescriptor<?> rowDescriptor = selectionModelDescriptor.getCollectionDescriptor() .getElementDescriptor(); ICompositeValueConnector rowConnectorPrototype = getConnectorFactory().createCompositeValueConnector( selectionModelDescriptor.getName() + "Element", rowDescriptor.getToHtmlProperty()); ICollectionConnector viewSelectionConnector = getConnectorFactory().createCollectionConnector( selectionModelDescriptor.getName(), getMvcBinder(), rowConnectorPrototype); ICollectionConnectorProvider viewConnector = (ICollectionConnectorProvider) view.getConnector(); bindSelectionConnector(viewConnector, viewSelectionConnector); IConfigurableCollectionConnectorProvider wrapperConnector = getConnectorFactory() .createConfigurableCollectionConnectorProvider(ModelRefPropertyConnector.THIS_PROPERTY, null); wrapperConnector.addChildConnector(viewSelectionConnector); wrapperConnector.addChildConnector(viewConnector); wrapperConnector.setCollectionConnectorProvider(viewConnector); view.setConnector(wrapperConnector); } if (viewDescriptor.getItemSelectionAction() != null) { ((IItemSelectable) view.getConnector()).addItemSelectionListener( new ConnectorActionAdapter<>(viewDescriptor.getItemSelectionAction(), getActionFactory(), actionHandler, view)); } if (viewDescriptor.getPaginationViewDescriptor() != null) { IView<E> paginationView = createPaginationView(viewDescriptor.getPaginationViewDescriptor(), view, actionHandler, locale); paginationView.setParent(view); view.setPeer(decorateWithPaginationView(view.getPeer(), paginationView.getPeer())); ((ICollectionConnectorProvider) view.getConnector()).getCollectionConnector().addSelectionChangeListener( new ISelectionChangeListener() { @Override public void selectionChange(SelectionChangeEvent evt) { IValueConnector modelConnector = ((ICollectionConnector) evt.getSource()).getModelConnector(); if (modelConnector != null) { // Fixes bug #1181 IPageable pageable = modelConnector.getModelProvider().getModel(); if (pageable != null) { int[] selectedIndices = evt.getNewSelection(); pageable.setSelectedRecordCount(selectedIndices == null ? 0 : selectedIndices.length); } } } }); } if (viewDescriptor.isAutoSelectFirstRow()) { attachDefaultCollectionListener(((ICollectionConnectorProvider) view.getConnector()).getCollectionConnector()); } } } /** * Gets enumeration icon dimension. * * @param propertyViewDescriptor * the property view descriptor * @return the enumeration icon dimension */ protected Dimension getEnumerationIconDimension(IPropertyViewDescriptor propertyViewDescriptor) { Dimension iconSize = getIconFactory().getTinyIconSize(); if (propertyViewDescriptor instanceof IEnumerationPropertyViewDescriptor && ((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).getEnumIconDimension() != null) { iconSize = ((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).getEnumIconDimension(); } return iconSize; } /** * Decorates a view with a pagination view. * * @param viewPeer * the collection view to decorate. * @param paginationViewPeer * the pagination view to use. * @return the assembled view decorated with pagination view. */ protected abstract E decorateWithPaginationView(E viewPeer, E paginationViewPeer); private ICollectionConnectorProvider createCompositeNodeGroupConnector(ITreeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale, ICompositeTreeLevelDescriptor subtreeViewDescriptor, int depth) { ICollectionDescriptorProvider<?> nodeGroupModelDescriptor = ((ICollectionDescriptorProvider<?>) subtreeViewDescriptor .getNodeGroupDescriptor().getModelDescriptor()); IConfigurableCollectionConnectorListProvider nodeGroupPrototypeConnector = connectorFactory .createConfigurableCollectionConnectorListProvider(nodeGroupModelDescriptor.getName() + "Element", subtreeViewDescriptor.getNodeGroupDescriptor().getRenderedProperty()); List<ICollectionConnectorProvider> subtreeConnectors = new ArrayList<>(); if (subtreeViewDescriptor.getChildrenDescriptors() != null && depth < viewDescriptor.getMaxDepth()) { for (ITreeLevelDescriptor childDescriptor : subtreeViewDescriptor.getChildrenDescriptors()) { if (actionHandler.isAccessGranted(childDescriptor)) { try { actionHandler.pushToSecurityContext(childDescriptor); ICollectionConnectorProvider childConnector = createNodeGroupConnector(viewDescriptor, actionHandler, locale, childDescriptor, depth + 1); nodeGroupPrototypeConnector.addChildConnector(childConnector.getId(), childConnector); subtreeConnectors.add(childConnector); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } } nodeGroupPrototypeConnector.setCollectionConnectorProviders(subtreeConnectors); if (nodeGroupPrototypeConnector instanceof AbstractCompositeValueConnector) { ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setDisplayValue( subtreeViewDescriptor.getNodeGroupDescriptor().getI18nName(actionHandler, locale)); ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setDisplayDescription( subtreeViewDescriptor.getNodeGroupDescriptor().getI18nDescription(actionHandler, locale)); ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setDisplayIcon( subtreeViewDescriptor.getNodeGroupDescriptor().getIcon()); ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setIconImageURLProvider( viewDescriptor.getIconImageURLProvider()); } ICollectionConnector nodeGroupCollectionConnector = connectorFactory.createCollectionConnector( nodeGroupModelDescriptor.getName(), mvcBinder, nodeGroupPrototypeConnector); return nodeGroupCollectionConnector; } /** * Creates an empty view whenever this specific view descriptor is not * supported. * * @param viewDescriptor * the view descriptor being the root of the view hierarchy to be * constructed. * @param actionHandler * the object responsible for executing the view actions (generally * the frontend controller itself). * @param locale * the locale the view must use for i18n. * @return the empty view. */ private IView<E> createEmptyView(IViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { IValueConnector connector = getConnectorFactory().createValueConnector(ModelRefPropertyConnector.THIS_PROPERTY); E viewComponent = createEmptyComponent(); return constructView(viewComponent, viewDescriptor, connector); } private ICollectionConnectorProvider createNodeGroupConnector(ITreeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale, ITreeLevelDescriptor subtreeViewDescriptor, int depth) { ICollectionConnectorProvider connector = null; if (subtreeViewDescriptor instanceof ICompositeTreeLevelDescriptor) { connector = createCompositeNodeGroupConnector(viewDescriptor, actionHandler, locale, (ICompositeTreeLevelDescriptor) subtreeViewDescriptor, depth); } else if (subtreeViewDescriptor instanceof ISimpleTreeLevelDescriptor) { connector = createSimpleNodeGroupConnector(viewDescriptor, actionHandler, locale, (ISimpleTreeLevelDescriptor) subtreeViewDescriptor, depth); } if (connector instanceof AbstractCompositeValueConnector) { ((AbstractCompositeValueConnector) connector).setDisplayValue( subtreeViewDescriptor.getNodeGroupDescriptor().getI18nName(actionHandler, locale)); ((AbstractCompositeValueConnector) connector).setDisplayDescription( subtreeViewDescriptor.getNodeGroupDescriptor().getI18nDescription(actionHandler, locale)); ((AbstractCompositeValueConnector) connector).setDisplayIcon( subtreeViewDescriptor.getNodeGroupDescriptor().getIcon()); ((AbstractCompositeValueConnector) connector).setIconImageURLProvider(viewDescriptor.getIconImageURLProvider()); } return connector; } private ICollectionConnectorProvider createSimpleNodeGroupConnector(ITreeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale, ISimpleTreeLevelDescriptor subtreeViewDescriptor, int depth) { ICollectionPropertyDescriptor<?> nodeGroupModelDescriptor = (ICollectionPropertyDescriptor<?>) subtreeViewDescriptor .getNodeGroupDescriptor().getModelDescriptor(); IConfigurableCollectionConnectorProvider nodeGroupPrototypeConnector = connectorFactory .createConfigurableCollectionConnectorProvider(nodeGroupModelDescriptor.getName() + "Element", subtreeViewDescriptor.getNodeGroupDescriptor().getRenderedProperty()); ITreeLevelDescriptor childDescriptor = subtreeViewDescriptor.getChildDescriptor(); if (childDescriptor != null && depth < viewDescriptor.getMaxDepth() && actionHandler.isAccessGranted( childDescriptor)) { try { actionHandler.pushToSecurityContext(childDescriptor); ICollectionConnectorProvider childConnector = createNodeGroupConnector(viewDescriptor, actionHandler, locale, childDescriptor, depth + 1); nodeGroupPrototypeConnector.addChildConnector(childConnector.getId(), childConnector); nodeGroupPrototypeConnector.setCollectionConnectorProvider(childConnector); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } if (nodeGroupPrototypeConnector instanceof AbstractCompositeValueConnector) { ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setDisplayValue( subtreeViewDescriptor.getNodeGroupDescriptor().getI18nName(actionHandler, locale)); ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setDisplayDescription( subtreeViewDescriptor.getNodeGroupDescriptor().getI18nDescription(actionHandler, locale)); ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setDisplayIcon( subtreeViewDescriptor.getNodeGroupDescriptor().getIcon()); ((AbstractCompositeValueConnector) nodeGroupPrototypeConnector).setIconImageURLProvider( viewDescriptor.getIconImageURLProvider()); } ICollectionConnector nodeGroupCollectionConnector = connectorFactory.createCollectionConnector( nodeGroupModelDescriptor.getName(), mvcBinder, nodeGroupPrototypeConnector); return nodeGroupCollectionConnector; } /** * Is live debug UI structure. * * @return the boolean */ protected boolean isLiveDebugUI() { return liveDebugUI; } /** * Sets live debug UI structure. * * @param liveDebugUI * the live debug uI structure */ public void setLiveDebugUI(boolean liveDebugUI) { this.liveDebugUI = liveDebugUI; } /** * Complete description with live debug uI. * * @param viewDescriptor * the view descriptor * @param viewDescription * the view description * @return the completed view description. */ protected String completeDescriptionWithLiveDebugUI(IViewDescriptor viewDescriptor, String viewDescription) { if (isLiveDebugUI()) { if (viewDescriptor.getPermId() != null) { if (viewDescription == null) { viewDescription = ""; } else { viewDescription = viewDescription + " "; } viewDescription = viewDescription + "(Descriptor PermId -> [" + viewDescriptor.getPermId() + "])"; } } return viewDescription; } /** * Connector action adapter. * * @param <E> * the actual component type. * @param <F> * the actual action type. * @author Vincent Vandenschrick */ protected static class ConnectorActionAdapter<E, F> implements IItemSelectionListener, IValueChangeListener, ICloneable { private final IAction actionDelegate; private final IActionFactory<F, E> actionFactory; private final IActionHandler actionHandler; private final IView<E> view; /** * Constructs a new {@code ConnectorActionAdapter} instance. * * @param actionDelegate * the action to trigger when the connector value/selection * changes. * @param actionFactory * the action factory. * @param actionHandler * the action handler. * @param view * the view to use in the context. */ public ConnectorActionAdapter(IAction actionDelegate, IActionFactory<F, E> actionFactory, IActionHandler actionHandler, IView<E> view) { this.actionDelegate = actionDelegate; this.actionFactory = actionFactory; this.actionHandler = actionHandler; this.view = view; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public ConnectorActionAdapter<E, F> clone() { try { return (ConnectorActionAdapter<E, F>) super.clone(); } catch (CloneNotSupportedException ex) { // Cannot happen. return null; } } /** * {@inheritDoc} */ @Override public void selectedItemChange(ItemSelectionEvent event) { Object actionParam = event.getSelectedItem(); triggerAction(actionParam); } /** * {@inheritDoc} */ @Override public void valueChange(ValueChangeEvent evt) { IValueConnector viewConnector = (IValueConnector) evt.getSource(); IValueConnector modelConnector = viewConnector.getModelConnector(); if (modelConnector != null && !ObjectUtils.equals(evt.getNewValue(), modelConnector.getConnectorValue())) { if (modelConnector.getConnectorValue() instanceof Map<?, ?> && modelConnector .getModelDescriptor() instanceof IReferencePropertyDescriptor<?> && viewConnector instanceof IRenderableCompositeValueConnector && ((IRenderableCompositeValueConnector) viewConnector).getRenderingConnector() != null) { modelConnector = ((IRenderableCompositeValueConnector) viewConnector).getRenderingConnector() .getModelConnector(); } // this is not a model notification, so arm to trigger the action once // the model is actually updated. modelConnector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent modelEvt) { // This is a 1 shot event. ((IValueChangeSource) modelEvt.getSource()).removeValueChangeListener(this); triggerAction(modelEvt.getOldValue()); } }); } } private void triggerAction(Object actionParam) { Map<String, Object> context = actionFactory.createActionContext(actionHandler, view, view.getConnector(), null, view.getPeer()); context.put(ActionContextConstants.ACTION_PARAM, actionParam); actionHandler.execute(actionDelegate, context); } } /** * Stores user table preferences. * * @param tableId * the table id used as preference key in the user store. * @param columnPrefs * the array of {columnId,columnSize} for the table * @param actionHandler * the action handler. */ @Override public void storeTablePreferences(String tableId, Object[][] columnPrefs, IActionHandler actionHandler) { if (actionHandler.getSubject() != null) { StringBuilder buff = new StringBuilder(); for (int i = 0; i < columnPrefs.length; i++) { if (i > 0) { buff.append("!"); } buff.append(columnPrefs[i][0]).append(",").append(columnPrefs[i][1]); if (columnPrefs[i].length > 2) { buff.append(",").append(columnPrefs[i][2]); } } actionHandler.putUserPreference(tableId, buff.toString()); } } /** * Reworks column view descriptors to align with user preferences. * * @param viewDescriptor * the table view descriptor. * @param actionHandler * the action handler to load the user preferences from. * @return an ordered map of column view descriptors and (widths, visibility) pairs. */ protected Map<IPropertyViewDescriptor, Object[]> getUserColumnViewDescriptors(ITableViewDescriptor viewDescriptor, IActionHandler actionHandler) { Object[][] columnPrefs = null; if (viewDescriptor.getPermId() != null && actionHandler.getSubject() != null) { String prefs = actionHandler.getUserPreference(viewDescriptor.getPermId()); if (prefs != null) { String[] columns = prefs.split("!"); columnPrefs = new Object[columns.length][3]; for (int i = 0; i < columns.length; i++) { String[] column = columns[i].split(","); Boolean visibility = column.length > 2 ? Boolean.valueOf(column[2]) : Boolean.TRUE; columnPrefs[i] = new Object[]{column[0], Integer.valueOf(column[1]), visibility}; } } } Map<IPropertyViewDescriptor, Object[]> userColumnViewDescriptors = new LinkedHashMap<>(); if (columnPrefs == null) { for (IPropertyViewDescriptor columnViewDescriptor : viewDescriptor.getColumnViewDescriptors()) { userColumnViewDescriptors.put(columnViewDescriptor, null); } } else { Map<String, IPropertyViewDescriptor> columnsDirectory = new LinkedHashMap<>(); for (IPropertyViewDescriptor columnViewDescriptor : viewDescriptor.getColumnViewDescriptors()) { columnsDirectory.put(computeColumnIdentifier(viewDescriptor, columnViewDescriptor), columnViewDescriptor); } for (Object[] columnPref : columnPrefs) { //noinspection SuspiciousMethodCalls IPropertyViewDescriptor userColumn = columnsDirectory.remove(columnPref[0]); if (userColumn != null) { userColumnViewDescriptors.put(userColumn, new Object[]{columnPref[1], columnPref[2]}); } } // Add remaining new columns for (IPropertyViewDescriptor extraColumn : columnsDirectory.values()) { userColumnViewDescriptors.put(extraColumn, null); } } return userColumnViewDescriptors; } /** * Store tab selection preference. * * @param tabViewDescriptor * the tab view descriptor * @param selectedTabIndex * the selected tab index * @param actionHandler * the action handler */ protected void storeTabSelectionPreference(ITabViewDescriptor tabViewDescriptor, int selectedTabIndex, IActionHandler actionHandler) { if (tabViewDescriptor.getPermId() != null) { if (actionHandler.getSubject() != null) { actionHandler.putUserPreference(tabViewDescriptor.getPermId(), Integer.toString(selectedTabIndex)); } } } /** * Gets tab selection preference. * * @param tabViewDescriptor * the tab view descriptor * @param actionHandler * the action handler * @return the tab selection preference */ protected int getTabSelectionPreference(ITabViewDescriptor tabViewDescriptor, IActionHandler actionHandler) { if (tabViewDescriptor.getPermId() != null && actionHandler.getSubject() != null) { String tabSelectionPreference = actionHandler.getUserPreference(tabViewDescriptor.getPermId()); if (tabSelectionPreference != null) { return Integer.parseInt(tabSelectionPreference); } } return 0; } /** * Filters enumeration values if refined. * * @param enumerationValues * the original collection to filter. * @param propertyViewDescriptor * the property view descriptor for the enumeration. */ protected void filterEnumerationValues(List<String> enumerationValues, IPropertyViewDescriptor propertyViewDescriptor) { if (propertyViewDescriptor instanceof IEnumerationPropertyViewDescriptor) { Set<String> allowedValues = ((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).getAllowedValues(); Set<String> forbiddenValues = ((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).getForbiddenValues(); if (allowedValues != null && !allowedValues.isEmpty()) { enumerationValues.retainAll(allowedValues); } if (forbiddenValues != null && !forbiddenValues.isEmpty()) { enumerationValues.removeAll(forbiddenValues); } } } /** * Configures the color to be used to highlight mandatory labels. It defaults * to red, i.e. {@code 0xFFFF0000}. * * @param mandatoryPropertyColorHex * the mandatoryPropertyColorHex to set. */ public void setMandatoryPropertyColorHex(String mandatoryPropertyColorHex) { this.formLabelMandatoryPropertyColorHex = mandatoryPropertyColorHex; this.tableHeaderMandatoryPropertyColorHex = mandatoryPropertyColorHex; } /** * Decorates mandatory property label. Default is to append a "*". * * @param labelText * the original label text. * @return the decorated label text. */ protected String decorateMandatoryPropertyLabel(String labelText) { String decoratedLabelText; if (labelText != null) { decoratedLabelText = labelText + "*"; } else { decoratedLabelText = "*"; } return decoratedLabelText; } /** * Gets the formLabelMandatoryPropertyColorHex. * * @return the formLabelMandatoryPropertyColorHex. */ public String getFormLabelMandatoryPropertyColorHex() { return formLabelMandatoryPropertyColorHex; } /** * Sets the formLabelMandatoryPropertyColorHex. * * @param formLabelMandatoryPropertyColorHex * the formLabelMandatoryPropertyColorHex to set. */ public void setFormLabelMandatoryPropertyColorHex(String formLabelMandatoryPropertyColorHex) { this.formLabelMandatoryPropertyColorHex = formLabelMandatoryPropertyColorHex; } /** * Gets the tableHeaderMandatoryPropertyColorHex. * * @return the tableHeaderMandatoryPropertyColorHex. */ public String getTableHeaderMandatoryPropertyColorHex() { return tableHeaderMandatoryPropertyColorHex; } /** * Sets the tableHeaderMandatoryPropertyColorHex. * * @param tableHeaderMandatoryPropertyColorHex * the tableHeaderMandatoryPropertyColorHex to set. */ public void setTableHeaderMandatoryPropertyColorHex(String tableHeaderMandatoryPropertyColorHex) { this.tableHeaderMandatoryPropertyColorHex = tableHeaderMandatoryPropertyColorHex; } /** * Gets the componentCollectionFactory. * * @return the componentCollectionFactory. */ public IComponentCollectionFactory getComponentCollectionFactory() { return componentCollectionFactory; } /** * Sets the componentCollectionFactory. * * @param componentCollectionFactory * the componentCollectionFactory to set. */ public void setComponentCollectionFactory(IComponentCollectionFactory componentCollectionFactory) { this.componentCollectionFactory = componentCollectionFactory; } /** * Is allowed for client type. * * @param clientTypeAwareView * the property view * @param actionHandler * the action handler * @return the boolean */ protected boolean isAllowedForClientType(IClientTypeAware clientTypeAwareView, IActionHandler actionHandler) { List<String> forClientTypes = clientTypeAwareView.getForClientTypes(); if (forClientTypes == null) { return true; } String clientType = actionHandler.getClientType().name(); for (String allowedClientType : forClientTypes) { if (clientType.matches(".*" + allowedClientType + ".*")) { return true; } } return false; } /** * Trigger tab selection action. * * @param selectedIndex * the selected index * @param tabComponent * the tab component * @param tabViewDescriptor * the tab view descriptor * @param tabView * the tab view * @param actionHandler * the action handler */ protected void triggerTabSelectionAction(int selectedIndex, E tabComponent, ITabViewDescriptor tabViewDescriptor, BasicIndexedView<E> tabView, IActionHandler actionHandler) { IAction tabSelectionAction = tabViewDescriptor.getTabSelectionAction(); if (tabSelectionAction != null) { Map<String, Object> actionContext = getActionFactory().createActionContext(actionHandler, tabView, tabView.getConnector(), Integer.toString(selectedIndex), tabComponent); actionContext.put(ActionContextConstants.ACTION_PARAM, selectedIndex); actionHandler.execute(tabSelectionAction, actionContext); } } /** * Is default hide action when disabled boolean. * * @return the boolean */ public boolean getDefaultHideActionWhenDisabled() { return defaultHideActionWhenDisabled; } /** * Sets default hide action when disabled. * * @param defaultHideActionWhenDisabled * the default hide action when disabled */ public void setDefaultHideActionWhenDisabled(boolean defaultHideActionWhenDisabled) { this.defaultHideActionWhenDisabled = defaultHideActionWhenDisabled; } }