/* * 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.remote; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.zip.CRC32; import java.util.zip.Checksum; import org.jspresso.framework.action.ActionContextConstants; import org.jspresso.framework.action.IAction; import org.jspresso.framework.action.IActionHandler; import org.jspresso.framework.application.frontend.command.remote.IRemoteCommandHandler; import org.jspresso.framework.application.frontend.command.remote.RemoteAddCardCommand; import org.jspresso.framework.application.frontend.command.remote.RemoteAddRepeatedCommand; import org.jspresso.framework.application.frontend.command.remote.RemoteEditCommand; import org.jspresso.framework.application.frontend.command.remote.RemoteFocusCommand; import org.jspresso.framework.application.frontend.command.remote.RemoteValueCommand; import org.jspresso.framework.application.view.ControllerAwareViewFactory; import org.jspresso.framework.binding.AbstractCompositeValueConnector; import org.jspresso.framework.binding.ICollectionConnector; import org.jspresso.framework.binding.ICompositeValueConnector; import org.jspresso.framework.binding.IValueConnector; import org.jspresso.framework.binding.model.ModelRefPropertyConnector; import org.jspresso.framework.binding.remote.RemoteValueConnector; import org.jspresso.framework.gui.remote.IRemoteScrollable; import org.jspresso.framework.gui.remote.RAction; import org.jspresso.framework.gui.remote.RActionComponent; import org.jspresso.framework.gui.remote.RActionField; import org.jspresso.framework.gui.remote.RActionList; import org.jspresso.framework.gui.remote.RActionable; import org.jspresso.framework.gui.remote.RBorderContainer; import org.jspresso.framework.gui.remote.RCardContainer; import org.jspresso.framework.gui.remote.RCheckBox; import org.jspresso.framework.gui.remote.RColorField; import org.jspresso.framework.gui.remote.RComboBox; import org.jspresso.framework.gui.remote.RComponent; import org.jspresso.framework.gui.remote.RDateField; import org.jspresso.framework.gui.remote.RDecimalComponent; import org.jspresso.framework.gui.remote.RDecimalField; import org.jspresso.framework.gui.remote.RDurationField; import org.jspresso.framework.gui.remote.REmptyComponent; import org.jspresso.framework.gui.remote.REnumBox; import org.jspresso.framework.gui.remote.RForm; import org.jspresso.framework.gui.remote.RHtmlArea; import org.jspresso.framework.gui.remote.RIcon; import org.jspresso.framework.gui.remote.RImageComponent; import org.jspresso.framework.gui.remote.RIntegerField; import org.jspresso.framework.gui.remote.RLabel; import org.jspresso.framework.gui.remote.RLink; import org.jspresso.framework.gui.remote.RList; import org.jspresso.framework.gui.remote.RMap; import org.jspresso.framework.gui.remote.RNumericComponent; import org.jspresso.framework.gui.remote.RPasswordField; import org.jspresso.framework.gui.remote.RPercentField; import org.jspresso.framework.gui.remote.RRadioBox; import org.jspresso.framework.gui.remote.RRepeater; import org.jspresso.framework.gui.remote.RSecurityComponent; import org.jspresso.framework.gui.remote.RTabContainer; import org.jspresso.framework.gui.remote.RTextArea; import org.jspresso.framework.gui.remote.RTextComponent; import org.jspresso.framework.gui.remote.RTextField; import org.jspresso.framework.gui.remote.RTimeField; import org.jspresso.framework.gui.remote.RTree; 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.IColorPropertyDescriptor; import org.jspresso.framework.model.descriptor.IComponentDescriptor; import org.jspresso.framework.model.descriptor.IComponentDescriptorProvider; 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.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.IStringPropertyDescriptor; import org.jspresso.framework.model.descriptor.ITextPropertyDescriptor; import org.jspresso.framework.model.descriptor.ITimePropertyDescriptor; import org.jspresso.framework.server.remote.RemotePeerRegistryServlet; import org.jspresso.framework.state.remote.IRemoteStateOwner; import org.jspresso.framework.state.remote.IRemoteStateValueMapper; import org.jspresso.framework.state.remote.IRemoteValueStateFactory; import org.jspresso.framework.state.remote.RemoteValueState; import org.jspresso.framework.util.automation.IPermIdSource; import org.jspresso.framework.util.event.IValueChangeListener; import org.jspresso.framework.util.event.ValueChangeEvent; import org.jspresso.framework.util.format.IFormatter; import org.jspresso.framework.util.gui.ColorHelper; import org.jspresso.framework.util.gui.Dimension; import org.jspresso.framework.util.gui.ERenderingOptions; import org.jspresso.framework.util.gui.Font; import org.jspresso.framework.util.gui.FontHelper; import org.jspresso.framework.util.i18n.ITranslationProvider; import org.jspresso.framework.util.image.IScalableImageAware; import org.jspresso.framework.util.image.ImageHelper; import org.jspresso.framework.util.lang.DateDto; import org.jspresso.framework.util.remote.registry.IRemotePeerRegistry; import org.jspresso.framework.util.resources.server.ResourceProviderServlet; import org.jspresso.framework.util.uid.IGUIDGenerator; import org.jspresso.framework.view.BasicCompositeView; import org.jspresso.framework.view.BasicIndexedView; import org.jspresso.framework.view.BasicMapView; import org.jspresso.framework.view.IActionFactory; import org.jspresso.framework.view.ICompositeView; import org.jspresso.framework.view.IMapView; import org.jspresso.framework.view.IView; import org.jspresso.framework.view.ViewException; import org.jspresso.framework.view.action.ActionList; import org.jspresso.framework.view.action.ActionMap; import org.jspresso.framework.view.action.IDisplayableAction; import org.jspresso.framework.view.descriptor.EHorizontalAlignment; import org.jspresso.framework.view.descriptor.EHorizontalPosition; 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.IComponentViewDescriptor; import org.jspresso.framework.view.descriptor.IEnumerationPropertyViewDescriptor; 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.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.IStaticTextViewDescriptor; import org.jspresso.framework.view.descriptor.IStringPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.ITabViewDescriptor; 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.BasicTimePropertyViewDescriptor; /** * Abstract base implementation for remote views. * * @author Vincent Vandenschrick */ @SuppressWarnings("UnusedParameters") public abstract class AbstractRemoteViewFactory extends ControllerAwareViewFactory<RComponent, RIcon, RAction> { private boolean dateServerParse; private boolean durationServerParse; private IRemoteCommandHandler remoteCommandHandler; private IGUIDGenerator<String> guidGenerator; private boolean numberServerParse; private IRemotePeerRegistry remotePeerRegistry; private IRemoteStateValueMapper binaryStateValueMapper; private IRemoteStateValueMapper enumerationStateValueMapper; /** * Instantiates a new Abstract remote view factory. */ public AbstractRemoteViewFactory() { numberServerParse = false; dateServerParse = false; durationServerParse = false; binaryStateValueMapper = new IRemoteStateValueMapper() { @Override public Object getValueForState(RemoteValueState state, Object originalValue) { if (originalValue instanceof byte[]) { String valueForStateUrl = RemotePeerRegistryServlet.computeDownloadUrl(state.getGuid()); Checksum checksumEngine = new CRC32(); checksumEngine.update((byte[]) originalValue, 0, ((byte[]) originalValue).length); // we must add a check sum so that the client knows when the url // content changes. valueForStateUrl += ("&cs=" + checksumEngine.getValue()); return valueForStateUrl; } return originalValue; } @Override public Object getValueFromState(RemoteValueState state, Object originalValue) { return originalValue; } }; enumerationStateValueMapper = new IRemoteStateValueMapper() { @Override public Object getValueForState(RemoteValueState state, Object originalValue) { if (originalValue == null) { return ""; } return originalValue; } @Override public Object getValueFromState(RemoteValueState state, Object originalValue) { if ("".equals(originalValue)) { return null; } return originalValue; } }; } /** * {@inheritDoc} */ @Override protected RComponent applyComponentScrollability(RComponent viewComponent, IScrollableViewDescriptor viewDescriptor) { if (viewComponent instanceof IRemoteScrollable) { ((IRemoteScrollable) viewComponent).setVerticallyScrollable(viewDescriptor.isVerticallyScrollable()); ((IRemoteScrollable) viewComponent).setHorizontallyScrollable(viewDescriptor.isHorizontallyScrollable()); } return viewComponent; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createColorPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IColorPropertyDescriptor propertyDescriptor = (IColorPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); RComponent viewComponent; if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } ((RLabel) viewComponent).setMaxLength(10); } else { viewComponent = createRColorField(propertyViewDescriptor); String defaultColor = (String) propertyDescriptor.getDefaultValue(); ((RColorField) viewComponent).setDefaultColor(defaultColor); if (defaultColor == null && propertyDescriptor.isMandatory()) { ((RColorField) viewComponent).setResetEnabled(false); } } connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Creates a remote color field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RColorField createRColorField(IPropertyViewDescriptor viewDescriptor) { RColorField component = new RColorField(getGuidGenerator().generateGUID()); return component; } /** * Gets the getGuidGenerator(). * * @return the getGuidGenerator(). */ public IGUIDGenerator<String> getGuidGenerator() { return guidGenerator; } /** * {@inheritDoc} */ @Override protected void finishComponentConfiguration(IViewDescriptor viewDescriptor, ITranslationProvider translationProvider, Locale locale, IView<RComponent> view) { RComponent viewPeer = view.getPeer(); configureComponent(viewDescriptor, translationProvider, locale, viewPeer); } private void configureComponent(IViewDescriptor viewDescriptor, ITranslationProvider translationProvider, Locale locale, RComponent viewPeer) { viewPeer.setLabel(viewDescriptor.getI18nName(translationProvider, locale)); String viewDescription = viewDescriptor.getI18nDescription(translationProvider, locale); viewDescription = completeDescriptionWithLiveDebugUI(viewDescriptor, viewDescription); if (viewDescription != null && viewDescription.length() > 0) { viewPeer.setToolTip(viewDescription); } if (viewDescriptor.getForeground() != null && ColorHelper.isColorSpec(viewDescriptor.getForeground())) { viewPeer.setForeground(viewDescriptor.getForeground()); } if (viewDescriptor.getBackground() != null && ColorHelper.isColorSpec(viewDescriptor.getBackground())) { viewPeer.setBackground(viewDescriptor.getBackground()); } if (viewDescriptor.getFont() != null && FontHelper.isFontSpec(viewDescriptor.getFont())) { viewPeer.setFont(createFont(viewDescriptor.getFont())); } if (viewDescriptor.getIcon() != null) { viewPeer.setIcon(getIconFactory().getIcon(viewDescriptor.getIcon(), getIconFactory().getSmallIconSize())); } else { viewPeer.setIcon(null); } if (viewDescriptor.getStyleName() != null) { viewPeer.setStyleName(viewDescriptor.getStyleName()); } } private Font createFont(String fontString) { Font font = FontHelper.fromString(fontString); return font; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createActionView(IActionViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { IValueConnector connector = getConnectorFactory().createValueConnector(ModelRefPropertyConnector.THIS_PROPERTY); connector.setExceptionHandler(actionHandler); RActionComponent viewComponent = createRActionComponent(viewDescriptor); IView<RComponent> view = constructView(viewComponent, viewDescriptor, connector); ActionList actionList = viewDescriptor.getActionList(); if (actionList != null) { ERenderingOptions defaultRenderingOptions = ERenderingOptions.ICON; if (viewDescriptor.getRenderingOptions() != null) { defaultRenderingOptions = viewDescriptor.getRenderingOptions(); } boolean defaultHideActionWhenDisabled = getDefaultHideActionWhenDisabled(); if (actionList.getHideActionWhenDisabled() != null) { defaultHideActionWhenDisabled = actionList.getHideActionWhenDisabled(); } viewComponent.setActionList( createViewActionList(actionList, defaultRenderingOptions, defaultHideActionWhenDisabled, view, actionHandler, locale)); } else { RAction action = getActionFactory().createAction(viewDescriptor.getAction(), viewDescriptor.getPreferredSize(), actionHandler, view, locale); switch (viewDescriptor.getRenderingOptions()) { case ICON: action.setName(null); break; case LABEL: action.setIcon(null); break; default: break; } viewComponent.setAction(action); } return view; } /** * Creates a remote button component. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RActionComponent createRActionComponent(IActionViewDescriptor viewDescriptor) { RActionComponent component = new RActionComponent(getGuidGenerator().generateGUID()); return component; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createIntegerPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IIntegerPropertyDescriptor propertyDescriptor = (IIntegerPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector; RComponent viewComponent; IFormatter<Object, String> formatter = createIntegerFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); if (propertyViewDescriptor.isReadOnly()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } ((RLabel) viewComponent).setMaxLength(getFormatLength(formatter, getIntegerTemplateValue(propertyDescriptor))); } else { if (isNumberServerParse() || getOverloadedPattern(propertyViewDescriptor, propertyDescriptor) != null) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); viewComponent = createRTextField(propertyViewDescriptor); } else { connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); viewComponent = createRIntegerField(propertyViewDescriptor); } } connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Creates a remote integer field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RIntegerField createRIntegerField(IPropertyViewDescriptor viewDescriptor) { RIntegerField component = new RIntegerField(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote label. * * @param viewDescriptor * the component view descriptor. * @param bold * make it bold ? * @return the created remote component. */ protected RLabel createRLabel(IPropertyViewDescriptor viewDescriptor, boolean bold) { RLabel component = new RLabel(getGuidGenerator().generateGUID()); if (bold) { component.setFont(createFont(BOLD_FONT)); } return component; } /** * Creates a remote link. * * @param viewDescriptor * the component view descriptor. * @param bold * make it bold ? * @return the created remote component. */ protected RLink createRLink(IPropertyViewDescriptor viewDescriptor, boolean bold) { RLink component = new RLink(getGuidGenerator().generateGUID()); if (bold) { component.setFont(createFont(BOLD_FONT)); } return component; } /** * Gets the numberServerParse. * * @return the numberServerParse. */ protected boolean isNumberServerParse() { return numberServerParse; } /** * {@inheritDoc} */ @Override protected void decorateWithBorder(IView<RComponent> view, ITranslationProvider translationProvider, Locale locale) { view.getPeer().setBorderType(view.getDescriptor().getBorderType().name()); } /** * {@inheritDoc} */ @Override protected IView<RComponent> createHtmlPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IHtmlPropertyDescriptor propertyDescriptor = (IHtmlPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); IValueConnector connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); connector.setExceptionHandler(actionHandler); RHtmlArea viewComponent = createRHtmlArea(propertyViewDescriptor); viewComponent.setReadOnly(propertyViewDescriptor.isReadOnly()); if (propertyViewDescriptor instanceof IScrollableViewDescriptor) { viewComponent.setVerticallyScrollable( ((IScrollableViewDescriptor) propertyViewDescriptor).isVerticallyScrollable()); viewComponent.setHorizontallyScrollable( ((IScrollableViewDescriptor) propertyViewDescriptor).isHorizontallyScrollable()); } else { viewComponent.setVerticallyScrollable(true); viewComponent.setHorizontallyScrollable(false); } IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); viewComponent.setAction( getActionFactory().createAction(propertyViewDescriptor.getAction(), actionHandler, view, locale)); return view; } /** * Creates a remote html area. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RHtmlArea createRHtmlArea(IPropertyViewDescriptor viewDescriptor) { RHtmlArea component = new RHtmlArea(getGuidGenerator().generateGUID()); return component; } /** * Sets the guidGenerator. * * @param guidGenerator * the guidGenerator to set. */ public void setGuidGenerator(IGUIDGenerator<String> guidGenerator) { this.guidGenerator = guidGenerator; } /** * Sets the numberServerParse. * * @param numberServerParse * the numberServerParse to set. */ public void setNumberServerParse(boolean numberServerParse) { this.numberServerParse = numberServerParse; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createPasswordPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IPasswordPropertyDescriptor propertyDescriptor = (IPasswordPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); connector.setExceptionHandler(actionHandler); RPasswordField viewComponent = createRPasswordField(propertyViewDescriptor); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Creates a remote password field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RPasswordField createRPasswordField(IPropertyViewDescriptor viewDescriptor) { RPasswordField component = new RPasswordField(getGuidGenerator().generateGUID()); return component; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createCardView(ICardViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { RCardContainer viewComponent = createRCardContainer(viewDescriptor); List<String> cardNames = new ArrayList<>(); List<RComponent> cards = new ArrayList<>(); cardNames.add(ICardViewDescriptor.DEFAULT_CARD); cards.add(createEmptyComponent()); cardNames.add(ICardViewDescriptor.SECURITY_CARD); cards.add(createSecurityComponent()); BasicMapView<RComponent> view = constructMapView(viewComponent, viewDescriptor); viewComponent.setCardNames(cardNames.toArray(new String[cardNames.size()])); viewComponent.setCards(cards.toArray(new RComponent[cards.size()])); view.setConnector(createCardViewConnector(view, actionHandler, locale)); return view; } /** * Creates a remote card container. * * @param viewDescriptor * the card view descriptor. * @return the created remote component. */ protected RCardContainer createRCardContainer(ICardViewDescriptor viewDescriptor) { RCardContainer cardContainer = new RCardContainer(getGuidGenerator().generateGUID()); cardContainer.setState(((IRemoteValueStateFactory) getConnectorFactory()) .createRemoteValueState(getGuidGenerator().generateGUID(), viewDescriptor.getPermId())); return cardContainer; } /** * Gets the remoteCommandHandler. * * @return the remoteCommandHandler. */ protected IRemoteCommandHandler getRemoteCommandHandler() { return remoteCommandHandler; } /** * Sets the remoteCommandHandler. * * @param remoteCommandHandler * the remoteCommandHandler to set. */ public void setRemoteCommandHandler(IRemoteCommandHandler remoteCommandHandler) { this.remoteCommandHandler = remoteCommandHandler; } /** * Creates a remote text field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RTextField createRTextField(IPropertyViewDescriptor viewDescriptor) { RTextField component = new RTextField(getGuidGenerator().generateGUID()); return component; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createStringPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IStringPropertyDescriptor propertyDescriptor = (IStringPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); connector.setExceptionHandler(actionHandler); RComponent viewComponent; if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } } else { viewComponent = createRTextField(propertyViewDescriptor); } IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); if (viewComponent instanceof RTextField) { if (propertyViewDescriptor instanceof IStringPropertyViewDescriptor && ((IStringPropertyViewDescriptor) propertyViewDescriptor).getCharacterAction() != null) { ((RTextField) viewComponent).setCharacterAction(getActionFactory() .createAction(((IStringPropertyViewDescriptor) propertyViewDescriptor).getCharacterAction(), actionHandler, view, locale)); } } return view; } /** * {@inheritDoc} */ @Override public void focus(RComponent component) { RemoteFocusCommand focusCommand = new RemoteFocusCommand(); focusCommand.setTargetPeerGuid(component.getGuid()); getRemoteCommandHandler().registerCommand(focusCommand); } /** * {@inheritDoc} */ @Override public void edit(RComponent component) { RemoteEditCommand editCommand = new RemoteEditCommand(); editCommand.setTargetPeerGuid(component.getGuid()); getRemoteCommandHandler().registerCommand(editCommand); } /** * {@inheritDoc} */ @Override protected IView<RComponent> createPercentPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IPercentPropertyDescriptor propertyDescriptor = (IPercentPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IFormatter<Object, String> formatter = createPercentFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); IValueConnector connector; RComponent viewComponent; if (propertyViewDescriptor.isReadOnly()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } ((RLabel) viewComponent).setMaxLength(getFormatLength(formatter, getPercentTemplateValue(propertyDescriptor))); } else { if (isNumberServerParse() || getOverloadedPattern(propertyViewDescriptor, propertyDescriptor) != null) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); viewComponent = createRTextField(propertyViewDescriptor); } else { connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); viewComponent = createRPercentField(propertyViewDescriptor); ((RPercentField) viewComponent).setMaxFractionDigit(propertyDescriptor.getMaxFractionDigit()); } connector.setExceptionHandler(actionHandler); } connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Creates a remote percent field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RPercentField createRPercentField(IPropertyViewDescriptor viewDescriptor) { RPercentField component = new RPercentField(getGuidGenerator().generateGUID()); return component; } /** * Sets the dateServerParse. * * @param dateServerParse * the dateServerParse to set. */ public void setDateServerParse(boolean dateServerParse) { this.dateServerParse = dateServerParse; } /** * Sets the durationServerParse. * * @param durationServerParse * the durationServerParse to set. */ public void setDurationServerParse(boolean durationServerParse) { this.durationServerParse = durationServerParse; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createBinaryPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IBinaryPropertyDescriptor propertyDescriptor = (IBinaryPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); if (connector instanceof RemoteValueConnector) { final RemoteValueConnector rConnector = (RemoteValueConnector) connector; rConnector.setRemoteStateValueMapper(getBinaryStateValueMapper()); } connector.setExceptionHandler(actionHandler); RActionField viewComponent = createRActionField(propertyViewDescriptor, false); IView<RComponent> propertyView = constructView(viewComponent, propertyViewDescriptor, connector); RActionList actionList = new RActionList(getGuidGenerator().generateGUID()); List<RAction> binaryActions = createBinaryActions(propertyView, actionHandler, locale); actionList.setActions(binaryActions.toArray(new RAction[binaryActions.size()])); viewComponent.setActionLists(actionList); return propertyView; } /** * Gets binary state value mapper. * * @return the binary state value mapper */ protected IRemoteStateValueMapper getBinaryStateValueMapper() { return binaryStateValueMapper; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createBooleanPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IBooleanPropertyDescriptor propertyDescriptor = (IBooleanPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); connector.setExceptionHandler(actionHandler); RCheckBox viewComponent = createRCheckBox(propertyViewDescriptor); if (!propertyDescriptor.isMandatory()) { viewComponent.setTriState(true); } IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createDatePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { final IDatePropertyDescriptor propertyDescriptor = (IDatePropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector; RComponent viewComponent; final TimeZone timeZone = propertyDescriptor.isTimeZoneAware() ? actionHandler.getClientTimeZone() : actionHandler.getReferenceTimeZone(); IFormatter<?, String> formatter = createDateFormatter(propertyViewDescriptor, propertyDescriptor, timeZone, actionHandler, locale); if (propertyViewDescriptor.isReadOnly()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } ((RLabel) viewComponent).setMaxLength(getFormatLength(formatter, getDateTemplateValue(propertyDescriptor))); } else { if (isDateServerParse()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); } else { connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); ((RemoteValueConnector) connector).setRemoteStateValueMapper(getDateStateValueMapper(timeZone)); } viewComponent = createRDateField(propertyViewDescriptor); ((RDateField) viewComponent).setType(propertyDescriptor.getType().name()); ((RDateField) viewComponent).setSecondsAware(propertyDescriptor.isSecondsAware()); ((RDateField) viewComponent).setMillisecondsAware(propertyDescriptor.isMillisecondsAware()); String formatPattern = propertyDescriptor.getFormatPattern(); if (propertyViewDescriptor instanceof BasicDatePropertyViewDescriptor && ((BasicDatePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern() != null) { formatPattern = ((BasicDatePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern(); } ((RDateField) viewComponent).setFormatPattern(formatPattern); } connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Gets date state value mapper. * * @param timeZone * the time zone * @return the date state value mapper */ protected IRemoteStateValueMapper getDateStateValueMapper(final TimeZone timeZone) { return new IRemoteStateValueMapper() { @SuppressWarnings("MagicConstant") @Override public Object getValueFromState(RemoteValueState state, Object originalValue) { // We have to use a Date DTO to avoid any // transformation by the network layer Calendar fieldCalendar = Calendar.getInstance(timeZone); if (originalValue instanceof DateDto) { DateDto stateDate = (DateDto) originalValue; fieldCalendar.set(stateDate.getYear(), stateDate.getMonth(), stateDate.getDate(), stateDate.getHour(), stateDate.getMinute(), stateDate.getSecond()); fieldCalendar.set(Calendar.MILLISECOND, stateDate.getMillisecond()); if (fieldCalendar.getTime().getTime() >= 0 && fieldCalendar.getTime().getTime() < 24 * 3600 * 1000) { // This is a default date. Set it today. Calendar today = Calendar.getInstance(timeZone); fieldCalendar.set(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DATE)); } Date connectorDate = fieldCalendar.getTime(); return connectorDate; } return originalValue; } @Override public Object getValueForState(RemoteValueState state, Object originalValue) { if (originalValue instanceof Date) { Date connectorDate = (Date) originalValue; Calendar fieldCalendar = Calendar.getInstance(timeZone); fieldCalendar.setTime(connectorDate); DateDto stateDate = new DateDto(); stateDate.setYear(fieldCalendar.get(Calendar.YEAR)); stateDate.setMonth(fieldCalendar.get(Calendar.MONTH)); stateDate.setDate(fieldCalendar.get(Calendar.DATE)); stateDate.setHour(fieldCalendar.get(Calendar.HOUR_OF_DAY)); stateDate.setMinute(fieldCalendar.get(Calendar.MINUTE)); stateDate.setSecond(fieldCalendar.get(Calendar.SECOND)); stateDate.setMillisecond(fieldCalendar.get(Calendar.MILLISECOND)); return stateDate; } return originalValue; } }; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createDecimalPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IDecimalPropertyDescriptor propertyDescriptor = (IDecimalPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); if (propertyDescriptor instanceof IPercentPropertyDescriptor) { return createPercentPropertyView(propertyViewDescriptor, actionHandler, locale); } IValueConnector connector; RComponent viewComponent; IFormatter<Object, String> formatter = createDecimalFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); if (propertyViewDescriptor.isReadOnly()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } ((RLabel) viewComponent).setMaxLength(getFormatLength(formatter, getDecimalTemplateValue(propertyDescriptor))); } else { if (isNumberServerParse() || getOverloadedPattern(propertyViewDescriptor, propertyDescriptor) != null) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); viewComponent = createRTextField(propertyViewDescriptor); } else { connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); viewComponent = createRDecimalField(propertyViewDescriptor); ((RDecimalComponent) viewComponent).setMaxFractionDigit(propertyDescriptor.getMaxFractionDigit()); } connector.setExceptionHandler(actionHandler); } connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createDurationPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IDurationPropertyDescriptor propertyDescriptor = (IDurationPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector; RComponent viewComponent; IFormatter<?, String> formatter = createDurationFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); if (propertyViewDescriptor.isReadOnly()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } ((RLabel) viewComponent).setMaxLength(getFormatLength(formatter, getDurationTemplateValue(propertyDescriptor))); } else { if (isDurationServerParse()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); } else { connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); } viewComponent = createRDurationField(propertyViewDescriptor); if (propertyDescriptor.getMaxMillis() != null) { ((RDurationField) viewComponent).setMaxMillis(propertyDescriptor.getMaxMillis()); } else { ((RDurationField) viewComponent).setMaxMillis(-1); } } connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createEnumerationPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IEnumerationPropertyDescriptor propertyDescriptor = (IEnumerationPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IValueConnector connector; RComponent viewComponent; IFormatter<Object, String> formatter = createEnumerationFormatter(propertyDescriptor, actionHandler, locale); // it's important to keep this special case for enumeration property views that are read-only. // r/o enumeration property views, if not assigned an action, should be transmitted as a read-only combo-box. // If not, enumeration images will disappear (see bug #1200) if (propertyViewDescriptor.isReadOnly() && propertyViewDescriptor.getAction() != null) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); viewComponent = createRLink(propertyViewDescriptor, false); ((RLabel) viewComponent).setMaxLength( getFormatLength(formatter, getEnumerationTemplateValue(propertyDescriptor, actionHandler, locale))); } else { connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); List<String> values = new ArrayList<>(); List<String> translations = new ArrayList<>(); List<String> enumerationValues = new ArrayList<>(propertyDescriptor.getEnumerationValues()); filterEnumerationValues(enumerationValues, propertyViewDescriptor); if (!propertyDescriptor.isMandatory()) { enumerationValues.add(0, ""); } for (String value : enumerationValues) { values.add(value); if (value != null && propertyDescriptor.isTranslated()) { if ("".equals(value)) { translations.add(" "); } else { translations.add(propertyDescriptor.getI18nValue(value, actionHandler, locale)); } } else { if (value == null) { translations.add(" "); } else { translations.add(value); } } } if (propertyViewDescriptor instanceof IEnumerationPropertyViewDescriptor && ((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).isRadio()) { viewComponent = createRRadioBox(propertyViewDescriptor); ((RRadioBox) viewComponent).setOrientation( ((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).getOrientation().name()); } else { viewComponent = createRComboBox(propertyViewDescriptor); ((RComboBox) viewComponent).setReadOnly(propertyViewDescriptor.isReadOnly()); List<RIcon> icons = new ArrayList<>(); for (String value : enumerationValues) { icons.add( getIconFactory().getIcon(propertyDescriptor.getIconImageURL(value), getIconFactory().getTinyIconSize())); } ((RComboBox) viewComponent).setIcons(icons.toArray(new RIcon[icons.size()])); } ((REnumBox) viewComponent).setValues(values.toArray(new String[values.size()])); ((REnumBox) viewComponent).setTranslations(translations.toArray(new String[translations.size()])); } ((IRemoteStateOwner) connector).setRemoteStateValueMapper(getEnumerationStateValueMapper()); connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Gets enumeration state value mapper. * * @return the enumeration state value mapper */ protected IRemoteStateValueMapper getEnumerationStateValueMapper() { return enumerationStateValueMapper; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createImagePropertyView(final IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { final IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); if (propertyViewDescriptor.isReadOnly() || propertyViewDescriptor instanceof IImageViewDescriptor || !(propertyDescriptor instanceof IBinaryPropertyDescriptor)) { IValueConnector connector = getConnectorFactory().createValueConnector( propertyViewDescriptor.getModelDescriptor().getName()); connector.setExceptionHandler(actionHandler); if (connector instanceof RemoteValueConnector) { final RemoteValueConnector rConnector = (RemoteValueConnector) connector; rConnector.setRemoteStateValueMapper(new IRemoteStateValueMapper() { @Override public Object getValueForState(RemoteValueState state, Object originalValue) { if (originalValue != null) { Integer scaledWidth = null; Integer scaledHeight = null; if (propertyViewDescriptor instanceof IScalableImageAware) { scaledWidth = ((IScalableImageAware) propertyViewDescriptor).getScaledWidth(); scaledHeight = ((IScalableImageAware) propertyViewDescriptor).getScaledHeight(); } else if (propertyDescriptor instanceof IScalableImageAware) { scaledWidth = ((IScalableImageAware) propertyDescriptor).getScaledWidth(); scaledHeight = ((IScalableImageAware) propertyDescriptor).getScaledHeight(); } String valueForStateUrl = null; if (originalValue instanceof byte[] || scaledWidth != null || scaledHeight != null) { valueForStateUrl = RemotePeerRegistryServlet.computeImageDownloadUrl(state.getGuid(), scaledWidth, scaledHeight); byte[] checksumSource = null; if (originalValue instanceof byte[]) { checksumSource = ((byte[]) originalValue); } else if (originalValue instanceof String) { checksumSource = ((String) originalValue).getBytes(); } if (checksumSource != null) { Checksum checksumEngine = new CRC32(); checksumEngine.update(checksumSource, 0, checksumSource.length); // we must add a check sum so that the client knows when the url // content changes. valueForStateUrl += ("&cs=" + checksumEngine.getValue()); } } else if (originalValue instanceof String) { valueForStateUrl = ResourceProviderServlet.computeLocalResourceDownloadUrl((String) originalValue); } return valueForStateUrl; } return null; } @Override public Object getValueFromState(RemoteValueState state, Object originalValue) { if (originalValue instanceof String && ((String) originalValue).contains("base64")) { return ImageHelper.fromBase64Src((String) originalValue); } return originalValue; } }); } RImageComponent viewComponent = createRImageComponent(propertyViewDescriptor); if (propertyViewDescriptor instanceof IScrollableViewDescriptor) { viewComponent.setScrollable(((IScrollableViewDescriptor) propertyViewDescriptor).isScrollable()); } else { viewComponent.setScrollable(false); } IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); if (propertyViewDescriptor.getAction() != null) { RAction action = getActionFactory().createAction(propertyViewDescriptor.getAction(), actionHandler, view, locale); configurePropertyViewAction(propertyViewDescriptor, action); viewComponent.setAction(action); } return view; } else { return createBinaryPropertyView(propertyViewDescriptor, actionHandler, locale); } } /** * {@inheritDoc} */ @Override protected IView<RComponent> createStaticTextPropertyView(IStaticTextViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { RTextComponent viewComponent; if (propertyViewDescriptor.isMultiLine()) { viewComponent = createRHtmlArea(propertyViewDescriptor); ((RHtmlArea) viewComponent).setReadOnly(true); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } IValueConnector connector = getConnectorFactory().createValueConnector(null); connector.setExceptionHandler(actionHandler); connector.setConnectorValue(actionHandler.getTranslation(propertyViewDescriptor.getI18nTextKey(), locale)); IView<RComponent> propertyView = constructView(viewComponent, propertyViewDescriptor, connector); return propertyView; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createNumberPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { INumberPropertyDescriptor propertyDescriptor = (INumberPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IView<RComponent> view = super.createNumberPropertyView(propertyViewDescriptor, actionHandler, locale); if (view.getPeer() instanceof RNumericComponent) { ((RNumericComponent) view.getPeer()).setMaxValue(propertyDescriptor.getMaxValue()); ((RNumericComponent) view.getPeer()).setMinValue(propertyDescriptor.getMinValue()); ((RNumericComponent) view.getPeer()).setThousandsGroupingUsed(propertyDescriptor.isThousandsGroupingUsed()); } if (view.getConnector() instanceof RemoteValueConnector) { final RemoteValueConnector rConnector = (RemoteValueConnector) view.getConnector(); rConnector.setRemoteStateValueMapper(new IRemoteStateValueMapper() { @Override public Object getValueForState(RemoteValueState state, Object originalValue) { if (originalValue instanceof BigDecimal) { return ((BigDecimal) originalValue).doubleValue(); } if (originalValue instanceof BigInteger) { return ((BigInteger) originalValue).longValue(); } return originalValue; } @Override public Object getValueFromState(RemoteValueState state, Object originalValue) { return originalValue; } }); } return view; } /** * Override to set the property view name that will be useful on client-side. * <p/> * {@inheritDoc} */ @Override protected IView<RComponent> createPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); IView<RComponent> propertyView = super.createPropertyView(propertyViewDescriptor, actionHandler, locale); if (propertyView != null) { RComponent peer = propertyView.getPeer(); if (propertyDescriptor != null && propertyDescriptor.getName() != null) { peer.setLabel(propertyDescriptor.getI18nName(actionHandler, locale)); } if (peer instanceof RLabel) { configureAlignment((RLabel) peer, propertyViewDescriptor.getHorizontalAlignment()); } else if (peer instanceof RTextField) { configureAlignment((RTextField) peer, propertyViewDescriptor.getHorizontalAlignment()); } else if (peer instanceof RNumericComponent) { configureAlignment((RNumericComponent) peer, propertyViewDescriptor.getHorizontalAlignment()); } if (propertyViewDescriptor.getFocusGainedAction() != null) { peer.setFocusGainedAction(getActionFactory() .createAction(propertyViewDescriptor.getFocusGainedAction(), actionHandler, propertyView, locale)); } } return propertyView; } /** * Creates a remote action field. * * @param showTextField * does it actually show a text field ? * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RActionField createRActionField(IPropertyViewDescriptor viewDescriptor, boolean showTextField) { RActionField component = new RActionField(getGuidGenerator().generateGUID()); component.setShowTextField(showTextField); return component; } /** * Creates a remote check box. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RCheckBox createRCheckBox(IPropertyViewDescriptor viewDescriptor) { RCheckBox component = new RCheckBox(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote combo box. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RComboBox createRComboBox(IPropertyViewDescriptor viewDescriptor) { RComboBox component = new RComboBox(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote radio box. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RRadioBox createRRadioBox(IPropertyViewDescriptor viewDescriptor) { RRadioBox component = new RRadioBox(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote date field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RDateField createRDateField(IPropertyViewDescriptor viewDescriptor) { RDateField component = new RDateField(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote decimal field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RDecimalField createRDecimalField(IPropertyViewDescriptor viewDescriptor) { RDecimalField component = new RDecimalField(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote duration field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RDurationField createRDurationField(IPropertyViewDescriptor viewDescriptor) { RDurationField component = new RDurationField(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote image component. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RImageComponent createRImageComponent(IPropertyViewDescriptor viewDescriptor) { RImageComponent component = new RImageComponent(getGuidGenerator().generateGUID()); return component; } /** * Gets the dateServerParse. * * @return the dateServerParse. */ protected boolean isDateServerParse() { return dateServerParse; } /** * Gets the durationServerParse. * * @return the durationServerParse. */ protected boolean isDurationServerParse() { return durationServerParse; } private void configureAlignment(RTextField textField, EHorizontalAlignment horizontalAlignment) { if (horizontalAlignment != null) { textField.setHorizontalAlignment(horizontalAlignment.name()); } } private void configureAlignment(RLabel label, EHorizontalAlignment horizontalAlignment) { if (horizontalAlignment != null) { label.setHorizontalAlignment(horizontalAlignment.name()); } } private void configureAlignment(RNumericComponent numericField, EHorizontalAlignment horizontalAlignment) { if (horizontalAlignment != null) { numericField.setHorizontalAlignment(horizontalAlignment.name()); } } /** * Creates a remote text area. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RTextArea createRTextArea(IPropertyViewDescriptor viewDescriptor) { RTextArea component = new RTextArea(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote time field. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RTimeField createRTimeField(IPropertyViewDescriptor viewDescriptor) { RTimeField component = new RTimeField(getGuidGenerator().generateGUID()); return component; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createTextPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { ITextPropertyDescriptor propertyDescriptor = (ITextPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); IValueConnector connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); connector.setExceptionHandler(actionHandler); RTextArea viewComponent = createRTextArea(propertyViewDescriptor); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createTextualPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IStringPropertyDescriptor propertyDescriptor = (IStringPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IView<RComponent> view = super.createTextualPropertyView(propertyViewDescriptor, actionHandler, locale); if (view.getPeer() instanceof RTextComponent) { Integer maxLength = propertyDescriptor.getMaxLength(); if (maxLength != null && maxLength > 0) { ((RTextComponent) view.getPeer()).setMaxLength(maxLength); } } return view; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createTimePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { ITimePropertyDescriptor propertyDescriptor = (ITimePropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); IValueConnector connector; RComponent viewComponent; IFormatter<?, String> formatter = createTimeFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); if (propertyViewDescriptor.isReadOnly()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } ((RLabel) viewComponent).setMaxLength(getFormatLength(formatter, getTimeTemplateValue(propertyDescriptor))); } else { if (isDateServerParse()) { connector = getConnectorFactory().createFormattedValueConnector(propertyDescriptor.getName(), formatter); } else { connector = getConnectorFactory().createValueConnector(propertyDescriptor.getName()); final TimeZone serverTz = actionHandler.getReferenceTimeZone(); ((RemoteValueConnector) connector).setRemoteStateValueMapper(new IRemoteStateValueMapper() { @SuppressWarnings("MagicConstant") @Override public Object getValueFromState(RemoteValueState state, Object originalValue) { Calendar serverCalendar = Calendar.getInstance(serverTz); if (originalValue instanceof DateDto) { DateDto stateDate = (DateDto) originalValue; serverCalendar.set(stateDate.getYear(), stateDate.getMonth(), stateDate.getDate(), stateDate.getHour(), stateDate.getMinute(), stateDate.getSecond()); serverCalendar.set(Calendar.MILLISECOND, stateDate.getMillisecond()); Date connectorDate = serverCalendar.getTime(); return connectorDate; } return originalValue; } @Override public Object getValueForState(RemoteValueState state, Object originalValue) { if (originalValue instanceof Date) { Date connectorDate = (Date) originalValue; Calendar serverCalendar = Calendar.getInstance(serverTz); serverCalendar.setTime(connectorDate); DateDto stateDate = new DateDto(); stateDate.setYear(serverCalendar.get(Calendar.YEAR)); stateDate.setMonth(serverCalendar.get(Calendar.MONTH)); stateDate.setDate(serverCalendar.get(Calendar.DATE)); stateDate.setHour(serverCalendar.get(Calendar.HOUR_OF_DAY)); stateDate.setMinute(serverCalendar.get(Calendar.MINUTE)); stateDate.setSecond(serverCalendar.get(Calendar.SECOND)); stateDate.setMillisecond(serverCalendar.get(Calendar.MILLISECOND)); return stateDate; } return originalValue; } }); } viewComponent = createRTimeField(propertyViewDescriptor); ((RTimeField) viewComponent).setSecondsAware(propertyDescriptor.isSecondsAware()); ((RTimeField) viewComponent).setMillisecondsAware(propertyDescriptor.isMillisecondsAware()); String formatPattern = propertyDescriptor.getFormatPattern(); if (propertyViewDescriptor instanceof BasicTimePropertyViewDescriptor && ((BasicTimePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern() != null) { formatPattern = ((BasicTimePropertyViewDescriptor) propertyViewDescriptor).getFormatPattern(); } ((RTimeField) viewComponent).setFormatPattern(formatPattern); } connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected void addCard(IMapView<RComponent> cardView, IView<RComponent> card, String cardName) { cardView.addToChildrenMap(cardName, card); RCardContainer cardContainer = (RCardContainer) cardView.getPeer(); RComponent[] newCards = new RComponent[cardContainer.getCards().length + 1]; System.arraycopy(cardContainer.getCards(), 0, newCards, 0, cardContainer.getCards().length); newCards[newCards.length - 1] = card.getPeer(); cardContainer.setCards(newCards); String[] newCardNames = new String[cardContainer.getCardNames().length + 1]; System.arraycopy(cardContainer.getCardNames(), 0, newCardNames, 0, cardContainer.getCardNames().length); newCardNames[newCardNames.length - 1] = cardName; cardContainer.setCardNames(newCardNames); RemoteAddCardCommand command = new RemoteAddCardCommand(); command.setTargetPeerGuid(cardContainer.getGuid()); command.setCard(card.getPeer()); command.setCardName(cardName); getRemoteCommandHandler().registerCommand(command); } /** * {@inheritDoc} */ @Override protected IView<RComponent> createComponentView(IComponentViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { IComponentDescriptor<?> modelDescriptor = ((IComponentDescriptorProvider<?>) viewDescriptor.getModelDescriptor()) .getComponentDescriptor(); // Dynamic toolTips String toolTipProperty = computeComponentDynamicToolTip(viewDescriptor, modelDescriptor); ICompositeValueConnector connector = getConnectorFactory().createCompositeValueConnector( getConnectorIdForBeanView(viewDescriptor), toolTipProperty); RForm viewComponent = createRForm(viewDescriptor); viewComponent.setWidthResizeable(viewDescriptor.isWidthResizeable()); viewComponent.setColumnCount(viewDescriptor.getColumnCount()); viewComponent.setLabelsPosition(viewDescriptor.getLabelsPosition().name()); List<Integer> elementWidths = new ArrayList<>(); List<RComponent> elements = new ArrayList<>(); List<RComponent> elementLabels = new ArrayList<>(); List<String> labelHorizontalPositions = new ArrayList<>(); List<IView<RComponent>> propertyViews = new ArrayList<>(); IView<RComponent> view = constructView(viewComponent, viewDescriptor, connector); for (IPropertyViewDescriptor propertyViewDescriptor : viewDescriptor.getPropertyViewDescriptors()) { if (isAllowedForClientType(propertyViewDescriptor, actionHandler)) { String propertyName = null; IPropertyDescriptor propertyDescriptor = null; IModelDescriptor propertyModelDescriptor = propertyViewDescriptor.getModelDescriptor(); if (propertyModelDescriptor != null) { propertyName = propertyModelDescriptor.getName(); propertyDescriptor = ((IComponentDescriptorProvider<?>) viewDescriptor.getModelDescriptor()).getComponentDescriptor().getPropertyDescriptor(propertyName); if (propertyDescriptor == null) { throw new ViewException( "Property descriptor [" + propertyName + "] does not exist for model descriptor " + viewDescriptor .getModelDescriptor().getName() + "."); } } IView<RComponent> propertyView = createView(propertyViewDescriptor, actionHandler, locale); // Fix bug 782 propertyView.getPeer().setIcon(null); propertyView.setParent(view); boolean forbidden = !actionHandler.isAccessGranted(propertyViewDescriptor); if (forbidden) { RComponent securityComponent = createSecurityComponent(); securityComponent.setPreferredSize(new Dimension(1, 1)); propertyView.setPeer(securityComponent); } else { propertyViews.add(propertyView); } elements.add(propertyView.getPeer()); RLabel propertyLabel = createFormPropertyLabel(actionHandler, locale, propertyViewDescriptor, propertyDescriptor, propertyView, forbidden); elementLabels.add(propertyLabel); elementWidths.add(propertyViewDescriptor.getWidth()); EHorizontalPosition labelHorizontalPosition = propertyViewDescriptor.getLabelHorizontalPosition(); if (labelHorizontalPosition == null) { labelHorizontalPosition = viewDescriptor.getLabelsHorizontalPosition(); } if (labelHorizontalPosition == null) { labelHorizontalPosition = EHorizontalPosition.LEFT; } labelHorizontalPositions.add(labelHorizontalPosition.name()); if (propertyName != null) { connector.addChildConnector(propertyName, propertyView.getConnector()); } // already handled in createView. // if (propertyViewDescriptor.getReadabilityGates() != null) { // if (propertyViewDescriptor.getWritabilityGates() != null) { // propertyView.getConnector().setLocallyWritable( // !propertyViewDescriptor.isReadOnly()); if (propertyView.getPeer() instanceof RActionable && propertyViewDescriptor.getAction() != null) { IView<RComponent> targetView; if (propertyDescriptor instanceof IRelationshipEndPropertyDescriptor) { targetView = propertyView; } else { targetView = view; } RAction action = getActionFactory().createAction(propertyViewDescriptor.getAction(), actionHandler, targetView, locale); configurePropertyViewAction(propertyViewDescriptor, action); ((RActionable) propertyView.getPeer()).setAction(action); } } } completePropertyViewsWithDynamicToolTips(connector, propertyViews, modelDescriptor); completePropertyViewsWithDynamicBackgrounds(connector, propertyViews, modelDescriptor); completePropertyViewsWithDynamicForegrounds(connector, propertyViews, modelDescriptor); completePropertyViewsWithDynamicFonts(connector, propertyViews, modelDescriptor); viewComponent.setElementWidths(elementWidths.toArray(new Integer[elementWidths.size()])); viewComponent.setElements(elements.toArray(new RComponent[elements.size()])); viewComponent.setElementLabels(elementLabels.toArray(new RComponent[elementLabels.size()])); viewComponent.setLabelHorizontalPositions( labelHorizontalPositions.toArray(new String[labelHorizontalPositions.size()])); if (viewDescriptor.isScrollable()) { view.setPeer(applyComponentScrollability(viewComponent, viewDescriptor)); } return view; } private RLabel createFormPropertyLabel(IActionHandler actionHandler, Locale locale, IPropertyViewDescriptor propertyViewDescriptor, IPropertyDescriptor propertyDescriptor, IView<RComponent> propertyView, boolean forbidden) { RLabel propertyLabel = createPropertyLabel(propertyViewDescriptor, propertyView.getPeer(), actionHandler, locale); if (!propertyViewDescriptor.isReadOnly() && propertyDescriptor != null && propertyDescriptor.isMandatory() && !(propertyDescriptor instanceof IBooleanPropertyDescriptor)) { if (propertyViewDescriptor.getLabelForeground() == null) { propertyLabel.setForeground(getFormLabelMandatoryPropertyColorHex()); } propertyLabel.setLabel(decorateMandatoryPropertyLabel(propertyLabel.getLabel())); } if (forbidden) { propertyLabel.setLabel(" "); propertyLabel.setIcon(null); } return propertyLabel; } /** * Creates a property label. * * @param propertyViewDescriptor * the property view descriptor. * @param propertyComponent * the property component. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the created property label. */ protected RLabel createPropertyLabel(IPropertyViewDescriptor propertyViewDescriptor, RComponent propertyComponent, ITranslationProvider translationProvider, Locale locale) { RLabel propertyLabel = createRLabel(null, false); String labelText = propertyViewDescriptor.getI18nName(translationProvider, locale); propertyLabel.setLabel(labelText); configurePropertyLabel(propertyLabel, propertyViewDescriptor); return propertyLabel; } private void configurePropertyLabel(RLabel propertyLabel, IPropertyViewDescriptor propertyViewDescriptor) { if (propertyViewDescriptor.getLabelFont() != null) { propertyLabel.setFont(createFont(propertyViewDescriptor.getLabelFont())); } if (propertyViewDescriptor.getLabelForeground() != null) { propertyLabel.setForeground(propertyViewDescriptor.getLabelForeground()); } if (propertyViewDescriptor.getLabelBackground() != null) { propertyLabel.setBackground(propertyViewDescriptor.getLabelBackground()); } if (propertyViewDescriptor.getIcon() != null) { propertyLabel.setIcon( getIconFactory().getIcon(propertyViewDescriptor.getIcon(), getIconFactory().getTinyIconSize())); } } /** * {@inheritDoc} */ @Override protected IView<RComponent> createMapView(IMapViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { RMap viewComponent = createRMap(viewDescriptor); String connectorId = ModelRefPropertyConnector.THIS_PROPERTY; if (viewDescriptor.getModelDescriptor() instanceof IPropertyDescriptor) { connectorId = viewDescriptor.getModelDescriptor().getName(); } ICompositeValueConnector connector = getConnectorFactory().createCompositeValueConnector(connectorId, null); connector.addChildConnector(getConnectorFactory().createValueConnector(viewDescriptor.getLongitudeProperty())); connector.addChildConnector(getConnectorFactory().createValueConnector(viewDescriptor.getLatitudeProperty())); connector.setExceptionHandler(actionHandler); IView<RComponent> view = constructView(viewComponent, viewDescriptor, connector); return view; } /** * Creates a remote map. * * @param viewDescriptor * the map view descriptor. * @return the created remote component. */ protected RMap createRMap(IMapViewDescriptor viewDescriptor) { return new RMap(getGuidGenerator().generateGUID()); } /** * Creates a remote form. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RForm createRForm(IComponentViewDescriptor viewDescriptor) { return new RForm(getGuidGenerator().generateGUID()); } /** * {@inheritDoc} */ @Override protected RComponent createSecurityComponent() { RComponent securityComponent = new RSecurityComponent(getGuidGenerator().generateGUID()); securityComponent.setState(new RemoteValueState(getGuidGenerator().generateGUID())); return securityComponent; } /** * {@inheritDoc} */ @Override protected void applyPreferredSize(RComponent component, Dimension preferredSize) { if (preferredSize != null) { component.setPreferredSize(preferredSize); } } /** * {@inheritDoc} */ @Override protected RComponent createEmptyComponent() { RComponent emptyComponent = new REmptyComponent(getGuidGenerator().generateGUID()); emptyComponent.setState(new RemoteValueState(getGuidGenerator().generateGUID())); return emptyComponent; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createSourceCodePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { return createTextPropertyView(propertyViewDescriptor, actionHandler, locale); } /** * {@inheritDoc} */ @Override protected IView<RComponent> createReferencePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IReferencePropertyDescriptor<?> propertyDescriptor = (IReferencePropertyDescriptor<?>) propertyViewDescriptor .getModelDescriptor(); String renderedProperty = computeRenderedProperty(propertyViewDescriptor); IValueConnector connector = getConnectorFactory().createCompositeValueConnector(propertyDescriptor.getName(), renderedProperty); connector.setExceptionHandler(actionHandler); RComponent viewComponent; if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createRLink(propertyViewDescriptor, false); } else { viewComponent = createRLabel(propertyViewDescriptor, false); } } else { viewComponent = createRActionField(propertyViewDescriptor, true); } IView<RComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); if (viewComponent instanceof RActionField) { if (propertyViewDescriptor instanceof IReferencePropertyViewDescriptor) { ((RActionField) viewComponent).setFieldEditable( ((IReferencePropertyViewDescriptor) propertyViewDescriptor).isAutoCompleteEnabled()); } else { ((RActionField) viewComponent).setFieldEditable(true); } RAction lovAction = createLovAction(view, actionHandler, locale); // lovAction.setName(actionHandler.getTranslation( // "lov.element.name", // new Object[] {propertyDescriptor.getReferencedDescriptor().getI18nName( // actionHandler, locale)}, locale)); lovAction.setDescription(actionHandler.getTranslation("lov.element.description", new Object[]{propertyDescriptor.getReferencedDescriptor().getI18nName(actionHandler, locale)}, locale) + IActionFactory.TOOLTIP_ELLIPSIS); // if (propertyDescriptor.getReferencedDescriptor().getIcon() != null) { // lovAction.setIcon(getIconFactory() // .getIcon(propertyDescriptor.getReferencedDescriptor().getIcon(), getIconFactory().getTinyIconSize())); // } RActionList actionList = new RActionList(getGuidGenerator().generateGUID()); actionList.setActions(lovAction); viewComponent.setActionLists(actionList); if (propertyViewDescriptor instanceof IStringPropertyViewDescriptor && ((IStringPropertyViewDescriptor) propertyViewDescriptor).getCharacterAction() != null) { ((RActionField) viewComponent).setCharacterAction(getActionFactory() .createAction(((IStringPropertyViewDescriptor) propertyViewDescriptor).getCharacterAction(), actionHandler, view, locale)); } } return view; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createListView(IListViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { ICollectionDescriptorProvider<?> modelDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor .getModelDescriptor()); IComponentDescriptor<?> rowDescriptor = modelDescriptor.getCollectionDescriptor().getElementDescriptor(); ICompositeValueConnector rowConnectorPrototype = getConnectorFactory().createCompositeValueConnector( modelDescriptor.getName() + "Element", rowDescriptor.getToHtmlProperty()); if (rowConnectorPrototype instanceof AbstractCompositeValueConnector) { ((AbstractCompositeValueConnector) rowConnectorPrototype).setDisplayIcon(viewDescriptor.getIcon()); ((AbstractCompositeValueConnector) rowConnectorPrototype).setIconImageURLProvider( viewDescriptor.getIconImageURLProvider()); } ICollectionConnector connector = getConnectorFactory().createCollectionConnector(modelDescriptor.getName(), getMvcBinder(), rowConnectorPrototype); RList viewComponent = createRList(viewDescriptor); viewComponent.setDisplayIcon(viewDescriptor.isDisplayIcon()); IView<RComponent> view = constructView(viewComponent, viewDescriptor, connector); String renderedProperty = viewDescriptor.getRenderedProperty(); if (renderedProperty != null) { IValueConnector cellConnector = createListConnector(renderedProperty, rowDescriptor); rowConnectorPrototype.addChildConnector(renderedProperty, cellConnector); } viewComponent.setSelectionMode(viewDescriptor.getSelectionMode().name()); if (viewDescriptor.getRowAction() != null) { viewComponent.setRowAction( getActionFactory().createAction(viewDescriptor.getRowAction(), actionHandler, view, locale)); } return view; } /** * Creates a remote list. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RList createRList(IListViewDescriptor viewDescriptor) { RList component = new RList(getGuidGenerator().generateGUID()); return component; } /** * Creates a remote tree. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RTree createRTree(ITreeViewDescriptor viewDescriptor) { RTree component = new RTree(getGuidGenerator().generateGUID()); return component; } /** * {@inheritDoc} */ @Override protected ICompositeView<RComponent> createBorderView(IBorderViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { RBorderContainer viewComponent = createRBorderContainer(viewDescriptor); BasicCompositeView<RComponent> view = constructCompositeView(viewComponent, viewDescriptor); List<IView<RComponent>> childrenViews = new ArrayList<>(); if (viewDescriptor.getNorthViewDescriptor() != null) { IView<RComponent> northView = createView(viewDescriptor.getNorthViewDescriptor(), actionHandler, locale); viewComponent.setNorth(northView.getPeer()); childrenViews.add(northView); } if (viewDescriptor.getWestViewDescriptor() != null) { IView<RComponent> westView = createView(viewDescriptor.getWestViewDescriptor(), actionHandler, locale); viewComponent.setWest(westView.getPeer()); childrenViews.add(westView); } if (viewDescriptor.getCenterViewDescriptor() != null) { IView<RComponent> centerView = createView(viewDescriptor.getCenterViewDescriptor(), actionHandler, locale); viewComponent.setCenter(centerView.getPeer()); childrenViews.add(centerView); } if (viewDescriptor.getEastViewDescriptor() != null) { IView<RComponent> eastView = createView(viewDescriptor.getEastViewDescriptor(), actionHandler, locale); viewComponent.setEast(eastView.getPeer()); childrenViews.add(eastView); } if (viewDescriptor.getSouthViewDescriptor() != null) { IView<RComponent> southView = createView(viewDescriptor.getSouthViewDescriptor(), actionHandler, locale); viewComponent.setSouth(southView.getPeer()); childrenViews.add(southView); } view.setChildren(childrenViews); return view; } /** * Creates a remote border container. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RBorderContainer createRBorderContainer(IBorderViewDescriptor viewDescriptor) { return new RBorderContainer(getGuidGenerator().generateGUID()); } /** * Complete property views with dynamic tool tips. * * @param connector * the connector * @param propertyViews * the property views * @param modelDescriptor * the model descriptor */ protected abstract void completePropertyViewsWithDynamicToolTips(ICompositeValueConnector connector, List<IView<RComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor); /** * Complete property views with dynamic backgrounds. * * @param connector * the connector * @param propertyViews * the property views * @param modelDescriptor * the model descriptor */ protected abstract void completePropertyViewsWithDynamicBackgrounds(ICompositeValueConnector connector, List<IView<RComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor); /** * Complete property views with dynamic foregrounds. * * @param connector * the connector * @param propertyViews * the property views * @param modelDescriptor * the model descriptor */ protected abstract void completePropertyViewsWithDynamicForegrounds(ICompositeValueConnector connector, List<IView<RComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor); /** * Complete property views with dynamic fonts. * * @param connector * the connector * @param propertyViews * the property views * @param modelDescriptor * the model descriptor */ protected abstract void completePropertyViewsWithDynamicFonts(ICompositeValueConnector connector, List<IView<RComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor); /** * Configures a property view action by initializing its static context. * * @param propertyViewDescriptor * the property view descriptor the action is attached to. * @param propertyViewAction * the action to configure. */ public void configurePropertyViewAction(IPropertyViewDescriptor propertyViewDescriptor, RAction propertyViewAction) { Map<String, Object> staticContext = new HashMap<>(); staticContext.put(ActionContextConstants.PROPERTY_VIEW_DESCRIPTOR, propertyViewDescriptor); propertyViewAction.putValue(IAction.STATIC_CONTEXT_KEY, staticContext); } /** * {@inheritDoc} */ @Override protected void showCardInPanel(RComponent cardsPeer, String cardName) { RemoteValueState cardState = cardsPeer.getState(); cardState.setValue(cardName); RemoteValueCommand command = new RemoteValueCommand(); command.setTargetPeerGuid(cardState.getGuid()); command.setValue(cardState.getValue()); getRemoteCommandHandler().registerCommand(command); } /** * {@inheritDoc} */ @Override protected void decorateWithActions(IViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale, IView<RComponent> view) { ActionMap actionMap = viewDescriptor.getActionMap(); ActionMap secondaryActionMap = viewDescriptor.getSecondaryActionMap(); RComponent peer = view.getPeer(); if (actionMap != null && actionHandler.isAccessGranted(actionMap)) { try { actionHandler.pushToSecurityContext(actionMap); // There might be default actions like LOV RActionList[] defaultActionLists = peer.getActionLists(); List<RActionList> declaredActionLists = createViewActionMap(actionMap, view, actionHandler, locale); if (defaultActionLists != null || declaredActionLists != null) { List<RActionList> viewActionLists = new ArrayList<>(); if (defaultActionLists != null) { viewActionLists.addAll(Arrays.asList(defaultActionLists)); } if (declaredActionLists != null) { viewActionLists.addAll(declaredActionLists); } peer.setActionLists(viewActionLists.toArray(new RActionList[viewActionLists.size()])); } } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } if (secondaryActionMap != null && actionHandler.isAccessGranted(secondaryActionMap)) { try { actionHandler.pushToSecurityContext(secondaryActionMap); // There might be default actions like LOV RActionList[] defaultSecondaryActionLists = peer.getSecondaryActionLists(); List<RActionList> declaredSecondaryActionLists = createViewActionMap(secondaryActionMap, view, actionHandler, locale); if (defaultSecondaryActionLists != null || declaredSecondaryActionLists != null) { List<RActionList> viewSecondaryActionLists = new ArrayList<>(); if (defaultSecondaryActionLists != null) { viewSecondaryActionLists.addAll(Arrays.asList(defaultSecondaryActionLists)); } if (declaredSecondaryActionLists != null) { viewSecondaryActionLists.addAll(declaredSecondaryActionLists); } peer.setSecondaryActionLists( viewSecondaryActionLists.toArray(new RActionList[viewSecondaryActionLists.size()])); } } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } /** * Creates a view toolbar based on an action map. * * @param actionMap * the action map to create the toolbar for. * @param view * the view to create the toolbar for. * @param actionHandler * the action handler used. * @param locale * the locale used. * @return the created tool bar. */ protected List<RActionList> createViewActionMap(ActionMap actionMap, IView<RComponent> view, IActionHandler actionHandler, Locale locale) { List<RActionList> viewActionLists = new ArrayList<>(); ERenderingOptions actionMapRenderingOptions = getDefaultActionMapRenderingOptions(); if (actionMap.getRenderingOptions() != null) { actionMapRenderingOptions = actionMap.getRenderingOptions(); } boolean defaultHideActionWhenDisabled = getDefaultHideActionWhenDisabled(); if (actionMap.getHideActionWhenDisabled() != null) { defaultHideActionWhenDisabled = actionMap.getHideActionWhenDisabled(); } for (ActionList nextActionList : actionMap.getActionLists(actionHandler)) { RActionList viewActionList = createViewActionList(nextActionList, actionMapRenderingOptions, defaultHideActionWhenDisabled, view, actionHandler, locale); if (viewActionList != null) { viewActionLists.add(viewActionList); } } return viewActionLists; } /** * Create view action list r action list. * * @param actionList * the action list * @param view * the view * @param actionMapRenderingOptions * the default rendering options * @param actionHandler * the action handler * @param locale * the locale * @return the r action list */ protected RActionList createViewActionList(ActionList actionList, ERenderingOptions actionMapRenderingOptions, boolean defaultHideActionWhenDisabled, IView<RComponent> view, IActionHandler actionHandler, Locale locale) { if (actionHandler.isAccessGranted(actionList)) { try { actionHandler.pushToSecurityContext(actionList); ERenderingOptions renderingOptions = actionMapRenderingOptions; if (actionList.getRenderingOptions() != null) { renderingOptions = actionList.getRenderingOptions(); } boolean hideActionWhenDisabled = defaultHideActionWhenDisabled; if (actionList.getHideActionWhenDisabled() != null) { hideActionWhenDisabled = actionList.getHideActionWhenDisabled(); } RActionList viewActionList = new RActionList(getGuidGenerator().generateGUID()); viewActionList.setCollapsable(actionList.isCollapsable()); viewActionList.setName(actionList.getName()); viewActionList.setDescription(actionList.getDescription()); viewActionList.setIcon(getIconFactory().getIcon(actionList.getIcon(), getIconFactory().getSmallIconSize())); List<RAction> actions = new ArrayList<>(); for (IDisplayableAction action : actionList.getActions()) { if (actionHandler.isAccessGranted(action)) { try { boolean hiddenWhenDisabled = hideActionWhenDisabled; if (action.getHiddenWhenDisabled() != null) { hiddenWhenDisabled = action.getHiddenWhenDisabled(); } actionHandler.pushToSecurityContext(action); RAction rAction = getActionFactory().createAction(action, getIconFactory().getSmallIconSize(), actionHandler, view, locale); rAction.setAcceleratorAsString(action.getAcceleratorAsString()); rAction.setHiddenWhenDisabled(hiddenWhenDisabled); actions.add(rAction); switch (renderingOptions) { case ICON: rAction.setName(null); break; case LABEL: rAction.setIcon(null); break; default: break; } } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } viewActionList.setActions(actions.toArray(new RAction[actions.size()])); return viewActionList; } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } return null; } /** * Gets the remotePeerRegistry. * * @return the remotePeerRegistry. */ public IRemotePeerRegistry getRemotePeerRegistry() { return remotePeerRegistry; } /** * Sets the remotePeerRegistry. * * @param remotePeerRegistry * the remotePeerRegistry to set. */ public void setRemotePeerRegistry(IRemotePeerRegistry remotePeerRegistry) { this.remotePeerRegistry = remotePeerRegistry; } /** * {@inheritDoc} */ @Override protected IView<RComponent> createTreeView(ITreeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { final ICompositeValueConnector connector = createTreeViewConnector(viewDescriptor, actionHandler, locale); RTree viewComponent = createRTree(viewDescriptor); viewComponent.setDisplayIcon(viewDescriptor.isDisplayIcon()); viewComponent.setExpanded(viewDescriptor.isExpanded()); IView<RComponent> view = constructView(viewComponent, viewDescriptor, connector); if (viewDescriptor.getRowAction() != null) { viewComponent.setRowAction( getActionFactory().createAction(viewDescriptor.getRowAction(), actionHandler, view, locale)); } return view; } /** * {@inheritDoc} */ @Override public IView<RComponent> constructView(RComponent viewComponent, IViewDescriptor descriptor, IValueConnector connector) { IView<RComponent> view = super.constructView(viewComponent, descriptor, connector); if (connector instanceof IPermIdSource) { ((IPermIdSource) connector).setPermId(descriptor.getPermId()); } if (viewComponent.getState() == null) { viewComponent.setState(((IRemoteStateOwner) connector).getState()); } viewComponent.setPermId(descriptor.getPermId()); return view; } /** * {@inheritDoc} */ @Override protected BasicIndexedView<RComponent> constructIndexedView(RComponent viewComponent, ITabViewDescriptor descriptor) { BasicIndexedView<RComponent> indexedView = super.constructIndexedView(viewComponent, descriptor); getRemotePeerRegistry().register(viewComponent); viewComponent.setPermId(getRemotePeerRegistry().registerPermId(descriptor.getPermId(), viewComponent.getGuid())); return indexedView; } /** * {@inheritDoc} */ @Override protected ICompositeView<RComponent> createTabView(final ITabViewDescriptor viewDescriptor, final IActionHandler actionHandler, Locale locale) { final RTabContainer viewComponent = createRTabContainer(viewDescriptor); final BasicIndexedView<RComponent> view = constructIndexedView(viewComponent, viewDescriptor); viewComponent.addPropertyChangeListener("selectedIndex", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { RTabContainer source = (RTabContainer) evt.getSource(); int selectedIndex = source.getSelectedIndex(); view.setCurrentViewIndex(selectedIndex); storeTabSelectionPreference(viewDescriptor, selectedIndex, actionHandler); triggerTabSelectionAction(selectedIndex, source, viewDescriptor, view, actionHandler); } }); List<RComponent> tabs = new ArrayList<>(); List<IView<RComponent>> childrenViews = new ArrayList<>(); for (IViewDescriptor childViewDescriptor : viewDescriptor.getChildViewDescriptors()) { if (actionHandler.isAccessGranted(childViewDescriptor)) { IView<RComponent> childView = createView(childViewDescriptor, actionHandler, locale); RComponent tab = childView.getPeer(); ERenderingOptions renderingOptions = getDefaultTabRenderingOptions(); if (viewDescriptor.getRenderingOptions() != null) { renderingOptions = viewDescriptor.getRenderingOptions(); } switch (renderingOptions) { case ICON: tab.setLabel(null); break; case LABEL: tab.setIcon(null); break; default: break; } tabs.add(tab); childrenViews.add(childView); } } viewComponent.setTabs(tabs.toArray(new RComponent[tabs.size()])); view.setChildren(childrenViews); view.setCurrentViewIndex(getTabSelectionPreference(viewDescriptor, actionHandler)); return view; } /** * Creates a remote tab container. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RTabContainer createRTabContainer(ITabViewDescriptor viewDescriptor) { return new RTabContainer(getGuidGenerator().generateGUID()); } /** * {@inheritDoc} */ @Override protected IView<RComponent> createRepeaterView(final IRepeaterViewDescriptor viewDescriptor, final IActionHandler actionHandler, final Locale locale) { ICollectionDescriptorProvider<?> modelDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor .getModelDescriptor()); final IView<RComponent> repeated = createView(viewDescriptor.getRepeatedViewDescriptor(), actionHandler, locale); ICompositeValueConnector elementConnectorPrototype = (ICompositeValueConnector) repeated.getConnector(); ICollectionConnector connector = getConnectorFactory().createCollectionConnector(modelDescriptor.getName(), getMvcBinder(), elementConnectorPrototype); RRepeater viewComponent = createRRepeater(viewDescriptor); IView<RComponent> view = constructView(viewComponent, viewDescriptor, connector); viewComponent.setSelectionMode(viewDescriptor.getSelectionMode().name()); if (viewDescriptor.getRowAction() != null) { viewComponent.setRowAction( getActionFactory().createAction(viewDescriptor.getRowAction(), actionHandler, view, locale)); } bindRepeaterConnector(connector, viewComponent, viewDescriptor, actionHandler, locale); return view; } /** * Bind repeater connector. * * @param connector * the connector * @param repeater * the repeater * @param viewDescriptor * the view descriptor * @param actionHandler * the action handler * @param locale * the locale */ protected void bindRepeaterConnector(ICollectionConnector connector, final RComponent repeater, final IRepeaterViewDescriptor viewDescriptor, final IActionHandler actionHandler, final Locale locale) { final Map<Integer, IView<RComponent>> childIds = new HashMap<>(); connector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { ICollectionConnector connector = (ICollectionConnector) evt.getSource(); int targetCount = connector.getChildConnectorCount(); List<RComponent> extraSections = new ArrayList<>(); for (int i = 0; i < targetCount; i++) { IValueConnector elementConnector = connector.getChildConnector(i); int childId = System.identityHashCode(elementConnector); if (!childIds.containsKey(childId)) { IView<RComponent> extraSection = createView(viewDescriptor.getRepeatedViewDescriptor(), actionHandler, locale); RComponent peer = extraSection.getPeer(); RemoteValueState state = ((IRemoteStateOwner) elementConnector).getState(); peer.setState(state); extraSections.add(peer); getMvcBinder().bind(extraSection.getConnector(), elementConnector); childIds.put(childId, extraSection); } } if (!extraSections.isEmpty()) { addRepeatedSections(repeater, extraSections); } } }); } /** * Add repeated sections. * * @param repeater * the repeater * @param extraSections * the extra sections */ protected void addRepeatedSections(RComponent repeater, List<RComponent> extraSections) { RemoteAddRepeatedCommand addRepeatedCommand = new RemoteAddRepeatedCommand(); addRepeatedCommand.setTargetPeerGuid(repeater.getGuid()); addRepeatedCommand.setNewSections(extraSections.toArray(new RComponent[extraSections.size()])); getRemoteCommandHandler().registerCommand(addRepeatedCommand); } /** * Creates a remote repeater container. * * @param viewDescriptor * the component view descriptor. * @return the created remote component. */ protected RRepeater createRRepeater(IRepeaterViewDescriptor viewDescriptor) { return new RRepeater(getGuidGenerator().generateGUID()); } }