blob: 0cbe04c988d4aafda2001910db61f29ecdf3d85d [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florian Pirchner - Initial implementation
*
*/
package org.eclipse.osbp.ecview.extension.strategy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.osbp.ecview.core.common.context.IViewContext;
import org.eclipse.osbp.ecview.core.common.model.binding.BindingFactory;
import org.eclipse.osbp.ecview.core.common.model.binding.YBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YBindingUpdateStrategy;
import org.eclipse.osbp.ecview.core.common.model.binding.YDetailValueBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YListBinding;
import org.eclipse.osbp.ecview.core.common.model.binding.YListBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YValueBinding;
import org.eclipse.osbp.ecview.core.common.model.binding.YValueBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YVisibilityProcessorValueBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YAlignment;
import org.eclipse.osbp.ecview.core.common.model.core.YBeanSlot;
import org.eclipse.osbp.ecview.core.common.model.core.YBeanSlotValueBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YCollectionBindable;
import org.eclipse.osbp.ecview.core.common.model.core.YConverter;
import org.eclipse.osbp.ecview.core.common.model.core.YDetailBeanSlot;
import org.eclipse.osbp.ecview.core.common.model.core.YElement;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddable;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableCollectionEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YField;
import org.eclipse.osbp.ecview.core.common.model.core.YLayout;
import org.eclipse.osbp.ecview.core.common.model.core.YSelectionBindable;
import org.eclipse.osbp.ecview.core.common.model.core.YTaggable;
import org.eclipse.osbp.ecview.core.common.model.core.YValueBindable;
import org.eclipse.osbp.ecview.core.common.model.core.YView;
import org.eclipse.osbp.ecview.core.common.model.datatypes.YDatadescription;
import org.eclipse.osbp.ecview.core.common.model.datatypes.impl.DatatypesFactoryImpl;
import org.eclipse.osbp.ecview.core.common.model.validation.ValidationFactory;
import org.eclipse.osbp.ecview.core.common.model.validation.YBeanValidationValidator;
import org.eclipse.osbp.ecview.core.common.model.validation.YUniqueAttributeValidator;
import org.eclipse.osbp.ecview.core.common.util.ECViewUtil;
import org.eclipse.osbp.ecview.core.extension.model.datatypes.ExtDatatypesFactory;
import org.eclipse.osbp.ecview.core.extension.model.datatypes.YDateTimeDatatype;
import org.eclipse.osbp.ecview.core.extension.model.datatypes.YDateTimeFormat;
import org.eclipse.osbp.ecview.core.extension.model.datatypes.YDateTimeResolution;
import org.eclipse.osbp.ecview.core.extension.model.extension.ExtensionModelFactory;
import org.eclipse.osbp.ecview.core.extension.model.extension.YBeanReferenceField;
import org.eclipse.osbp.ecview.core.extension.model.extension.YColumn;
import org.eclipse.osbp.ecview.core.extension.model.extension.YComboBox;
import org.eclipse.osbp.ecview.core.extension.model.extension.YDateTime;
import org.eclipse.osbp.ecview.core.extension.model.extension.YDecimalField;
import org.eclipse.osbp.ecview.core.extension.model.extension.YEnumComboBox;
import org.eclipse.osbp.ecview.core.extension.model.extension.YEnumOptionsGroup;
import org.eclipse.osbp.ecview.core.extension.model.extension.YFilteringComponent;
import org.eclipse.osbp.ecview.core.extension.model.extension.YNumericField;
import org.eclipse.osbp.ecview.core.extension.model.extension.YPasswordField;
import org.eclipse.osbp.ecview.core.extension.model.extension.YSuggestTextField;
import org.eclipse.osbp.ecview.core.extension.model.extension.YTab;
import org.eclipse.osbp.ecview.core.extension.model.extension.YTabSheet;
import org.eclipse.osbp.ecview.core.extension.model.extension.YTable;
import org.eclipse.osbp.ecview.core.extension.model.extension.YTextArea;
import org.eclipse.osbp.ecview.core.extension.model.extension.YVerticalLayout;
import org.eclipse.osbp.ecview.core.extension.model.extension.YVerticalLayoutCellStyle;
import org.eclipse.osbp.ecview.core.extension.model.extension.impl.ExtensionModelFactoryImpl;
import org.eclipse.osbp.ecview.core.util.emf.ModelUtil;
import org.eclipse.osbp.ecview.extension.api.ILayoutingStrategy;
import org.eclipse.osbp.ecview.extension.grid.CxGrid;
import org.eclipse.osbp.ecview.extension.grid.util.CxGridUtil;
import org.eclipse.osbp.ecview.extension.model.YBlobUploadComponent;
import org.eclipse.osbp.ecview.extension.model.YCollectionSuspect;
import org.eclipse.osbp.ecview.extension.model.YColumnInfo;
import org.eclipse.osbp.ecview.extension.model.YCustomDecimalField;
import org.eclipse.osbp.ecview.extension.model.YECviewFactory;
import org.eclipse.osbp.ecview.extension.model.YIconComboBox;
import org.eclipse.osbp.ecview.extension.model.YLayoutingInfo;
import org.eclipse.osbp.ecview.extension.model.YMaskedDecimalField;
import org.eclipse.osbp.ecview.extension.model.YMaskedTextField;
import org.eclipse.osbp.ecview.extension.model.YPairComboBox;
import org.eclipse.osbp.ecview.extension.model.YRichTextArea;
import org.eclipse.osbp.ecview.extension.model.YStrategyLayout;
import org.eclipse.osbp.ecview.extension.model.YSubTypeBaseSuspect;
import org.eclipse.osbp.ecview.extension.model.YSubTypeSuspect;
import org.eclipse.osbp.ecview.extension.model.YSuspect;
import org.eclipse.osbp.ecview.extension.model.YSuspectInfo;
import org.eclipse.osbp.ecview.extension.model.YTypedCompoundSuspect;
import org.eclipse.osbp.ecview.extension.model.YTypedSuspect;
import org.eclipse.osbp.ecview.extension.model.converter.YConverterFactory;
import org.eclipse.osbp.ecview.extension.model.converter.YCustomDecimalConverter;
import org.eclipse.osbp.ecview.extension.model.converter.YSimpleDecimalConverter;
import org.eclipse.osbp.ecview.extension.model.visibility.YSubTypeVisibilityProcessor;
import org.eclipse.osbp.ecview.extension.model.visibility.YVisibilityFactory;
import org.eclipse.osbp.ecview.extension.strategy.util.NamingConventionsUtil;
import org.eclipse.osbp.preferences.ProductConfiguration;
import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService;
import org.eclipse.osbp.ui.api.themes.EnumCssClass;
import org.eclipse.osbp.ui.api.useraccess.AbstractAuthorization.Action;
import org.eclipse.osbp.ui.api.useraccess.AbstractAuthorization.Group;
import org.eclipse.osbp.ui.api.useraccess.AbstractSubOrganization;
import org.eclipse.osbp.ui.api.useraccess.IOrganizationService;
import org.eclipse.osbp.ui.api.useraccess.IPosition;
import org.eclipse.osbp.ui.api.useraccess.IUserAccessService;
import org.eclipse.osbp.utils.functionnormalizer.api.FunctionTypingAPI;
import org.eclipse.osbp.utils.functionnormalizer.entities.FunctionType;
import org.eclipse.osbp.utils.themes.ui.VaaclipseUiTheme;
import org.eclipse.osbp.utils.themes.ui.VaaclipseUiTheme.ThemeList;
import org.eclipse.xtext.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class AbstractLayoutingStrategy.
*/
public abstract class AbstractLayoutingStrategy implements ILayoutingStrategy {
/** The filtered category. */
private final String filteredCategory;
/** The function typing api. */
private FunctionTypingAPI functionTypingApi;
/** The user access service. */
private IUserAccessService userAccessService;
/** The view context. */
private IViewContext viewContext;
private YLayoutingInfo layoutingInfo;
private IDSLMetadataService dslMetadataService;
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractLayoutingStrategy.class);
/**
* Only given category is shown.
*
* @param filteredCategory
* the filtered category
*/
public AbstractLayoutingStrategy(String filteredCategory) {
super();
this.filteredCategory = filteredCategory;
this.functionTypingApi = new FunctionTypingAPI();
}
public YLayoutingInfo getLayoutingInfo() {
return layoutingInfo;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.extension.api.ILayoutingStrategy#layout(org. eclipse .osbp.ecview.extension.model.YLayoutingInfo)
*/
@Override
public void layout(YLayoutingInfo layoutingInfo) {
this.layoutingInfo = layoutingInfo;
clean();
YStrategyLayout yLayout = layoutingInfo.getLayout();
layoutingInfo.getActiveSuspectInfos().clear();
YLayout layout = createContentLayout();
YEmbeddable content;
layoutingInfo.getView().getTags().add(TAG__AUTOBINDED);
viewContext = ModelUtil.getViewContext(yLayout);
userAccessService = viewContext.getService(IUserAccessService.class.getName());
dslMetadataService = viewContext.getService(IDSLMetadataService.class.getName());
// Identify if a TabSheet is necessary due to existing table or grid
if (isTabSheetNeeded(yLayout.getSuspects())) {
YTabSheet tabSheet;
tabSheet = ExtensionModelFactory.eINSTANCE.createYTabSheet();
YTab tab = ExtensionModelFactory.eINSTANCE.createYTab();
tab.setLabelI18nKey(getEntityI18nKey(yLayout.getSuspects()));
tab.setEmbeddable(layout);
tabSheet.getTabs().add(tab);
content = tabSheet;
} else {
content = layout;
}
// Creates YEmbeddables from YSuspects
for (YSuspect suspect : createSuspectList(yLayout)) {
if (filteredCategory != null && !"".equals(filteredCategory) && !suspect.getTags().contains(filteredCategory)) {
// filter the suspect
continue;
}
// Create a new suspect info.
YSuspectInfo suspectInfo = layoutingInfo.createSuspectInfo(suspect);
// add the suspectInfo as active suspect
layoutingInfo.getActiveSuspectInfos().add(suspectInfo);
YEmbeddable yEmbeddable = prepareElementForSuspect(suspectInfo);
if (yEmbeddable != null) {
addElement(content, yEmbeddable, suspectInfo);
}
}
layoutingInfo.setContent(content);
}
/**
* Removes elements tagged with #TAG__TO_BE_CLEANED from the view.
*/
private void clean() {
YView view = layoutingInfo.getView();
TreeIterator<Object> contents = EcoreUtil.getAllContents(view, true);
while (contents.hasNext()) {
Object element = contents.next();
if (element instanceof YTaggable) {
YTaggable taggable = (YTaggable) element;
if (taggable.getTags().contains(TAG__TO_BE_CLEANED)) {
EcoreUtil.remove(taggable);
}
}
}
}
/**
* Creates the suspect list.
*
* @param yLayout
* the y layout
* @return the array list
*/
private ArrayList<YSuspect> createSuspectList(YStrategyLayout yLayout) {
ArrayList<YSuspect> suspectList = new ArrayList<>(yLayout.getSuspects().size());
ArrayList<YSuspect> suspectCollectionList = new ArrayList<>(yLayout.getSuspects().size());
for (YSuspect ySuspect : yLayout.getSuspects()) {
if (ySuspect.getTags().contains(TAG__TABLE) || ySuspect.getTags().contains(TAG__GRID)) {
suspectCollectionList.add(ySuspect);
} else {
suspectList.add(ySuspect);
}
}
Collections.sort(suspectCollectionList, new SuspectComparator());
suspectList.addAll(suspectCollectionList);
return suspectList;
}
/**
* Adds the element.
*
* @param content
* the content
* @param element
* the element
* @param suspectInfo
* the suspect info
*/
private void addElement(YEmbeddable content, YEmbeddable element, YSuspectInfo suspectInfo) {
if (content instanceof YTabSheet) {
EList<YTab> tabs = ((YTabSheet) content).getTabs();
if (suspectInfo.getSuspect().getTags().contains(TAG__TABLE) || suspectInfo.getSuspect().getTags().contains(TAG__GRID)) {
YTab tab = ExtensionModelFactory.eINSTANCE.createYTab();
tab.setLabelI18nKey(suspectInfo.getSuspect().getLabelI18nKey());
YVerticalLayout layout = ExtensionModelFactory.eINSTANCE.createYVerticalLayout();
layout.addElement(element);
YVerticalLayoutCellStyle cellStyle = layout.addCellStyle(element);
cellStyle.setAlignment(YAlignment.FILL_FILL);
tab.setEmbeddable(layout);
tabs.add(tab);
} else {
// Gets the YLayout of the first tab to add the element
addElement((YLayout) tabs.get(0).getEmbeddable(), element);
}
} else {
addElement((YLayout) content, element);
}
}
/**
* Creates the content layout.
*
* @return the y layout
*/
protected abstract YLayout createContentLayout();
/**
* Adds the element.
*
* @param layout
* the layout
* @param element
* the element
*/
protected abstract void addElement(YLayout layout, YEmbeddable element);
/**
* Creates a new element for the given suspect. Handle bindings,...
*
* @param suspectInfo
* the suspect info
* @return the y embeddable
*/
protected YEmbeddable prepareElementForSuspect(YSuspectInfo suspectInfo) {
// create a new element for the given suspect
YEmbeddable yEmbeddable = createElementForSuspect(suspectInfo); // NOSONAR
return yEmbeddable;
}
/**
* Create the value or list bindings for the given element.
*
* @param suspectInfo
* the suspect info
* @param yEmbeddable
* the y embeddable
*/
protected void prepareValueBindings(YSuspectInfo suspectInfo, YEmbeddable yEmbeddable) {
YSuspect ySuspect = suspectInfo.getSuspect();
// iterate over all elements
for (YBindingEndpoint ep : ySuspect.getValueBindingEndpoints()) {
/*
* if yEmbeddable is a value bindable and ep a value binding
*/
if (ep instanceof YValueBindingEndpoint && yEmbeddable instanceof YValueBindable) {
YValueBindable yBindable = (YValueBindable) yEmbeddable;
// make a copy -> otherwise the suspect will be changed
YBindingEndpoint epCopy = EcoreUtil.copy(ep);
YValueBindingEndpoint yValueEP;
if (suspectInfo.getTags().contains(ILayoutingStrategy.TAG__RICH_TEXT__BLOB)) {
// if we need to bind the blob value, then we need to use a
// different endpoint
YRichTextArea richtText = (YRichTextArea) yEmbeddable;
yValueEP = richtText.createBlobValueEndpoint();
} else {
yValueEP = yBindable.createValueEndpoint();
}
YValueBinding yBinding = BindingFactory.eINSTANCE.createYValueBinding();
yBinding.setModelEndpoint((YValueBindingEndpoint) epCopy);
yBinding.setTargetEndpoint(yValueEP);
// register binding add suspect. Will be handled
// automatically.
suspectInfo.getBindings().add(yBinding);
/*
* if yEmbeddable is a selection bindable and ep a value binding
*/
} else if (ep instanceof YValueBindingEndpoint && yEmbeddable instanceof YSelectionBindable) {
YSelectionBindable yBindable = (YSelectionBindable) yEmbeddable;
// make a copy -> otherwise the suspect will be changed
YBindingEndpoint epCopy = EcoreUtil.copy(ep);
YValueBindingEndpoint yValueEP = yBindable.createSelectionEndpoint();
YValueBinding yBinding = BindingFactory.eINSTANCE.createYValueBinding();
yBinding.setModelEndpoint((YValueBindingEndpoint) epCopy);
yBinding.setTargetEndpoint(yValueEP);
// register binding add suspect. Will be handled
// automatically.
suspectInfo.getBindings().add(yBinding);
/*
* if yEmbeddable is a collection bindable and ep a list binding
*/
} else if (ep instanceof YListBindingEndpoint && yEmbeddable instanceof YCollectionBindable) {
YCollectionBindable yBindable = (YCollectionBindable) yEmbeddable;
// make a copy -> otherwise the suspect will be changed
YBindingEndpoint epCopy = EcoreUtil.copy(ep);
YEmbeddableCollectionEndpoint yListEP = yBindable.createCollectionEndpoint();
YListBinding yBinding = BindingFactory.eINSTANCE.createYListBinding();
yBinding.setModelEndpoint((YListBindingEndpoint) epCopy);
yBinding.setTargetEndpoint(yListEP);
// register binding add suspect. Will be handled
// automatically.
suspectInfo.getBindings().add(yBinding);
}
}
}
/**
* Creates the element for suspect.
*
* @param suspectInfo
* the suspect info
* @return the y embeddable
*/
protected YEmbeddable createElementForSuspect(YSuspectInfo suspectInfo) {
YSuspect ySuspect = suspectInfo.getSuspect();
YEmbeddable yEmbeddable = null;
if (ySuspect.getTags().contains(TAG__DECIMAL)) {
if (existFunctionsInProperties(ySuspect)) {
yEmbeddable = YECviewFactory.eINSTANCE.createYCustomDecimalField();
setCustomDecimalConverter(yEmbeddable, ySuspect);
} else {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYDecimalField();
((YDecimalField) yEmbeddable).setConverter(getConverter(ySuspect.getProperties()));
}
} else if (ySuspect.getTags().contains(TAG__TEXT)) {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYTextField();
} else if (ySuspect.getTags().contains(TAG__PASSWORD)) {
yEmbeddable = createPasswordField(ySuspect);
} else if (ySuspect.getTags().contains(TAG__SUGGEST_TEXT)) {
YTypedSuspect typedSuspect = (YTypedSuspect) ySuspect;
YSuggestTextField yField = ExtensionModelFactory.eINSTANCE.createYSuggestTextField();
// the type the field will query for matching entries
yField.setType(typedSuspect.getType());
yField.setTypeQualifiedName(typedSuspect.getTypeQualifiedName());
yField.setUseSuggestions(true);
// the caption and filter property
yField.setItemCaptionProperty(typedSuspect.getProperties().get(PROPERTY__ITEM_CAPTION));
yField.setItemFilterProperty(typedSuspect.getProperties().get(PROPERTY__ITEM_FILTER));
yField.setItemUUIDProperty(typedSuspect.getProperties().get(PROPERTY__ITEM_UUID));
yEmbeddable = yField;
} else if (ySuspect.getTags().contains(TAG__TEXTAREA)) {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYTextArea();
if (!ySuspect.getProperties().isEmpty()) {
try {
int rows = new Integer(ySuspect.getProperties().get(PROPERTY_TEXTAREA));
((YTextArea) yEmbeddable).setRows(rows);
} catch (NumberFormatException ex) {
// Do nothing!!!
}
}
yEmbeddable.getProperties().addAll(ySuspect.getProperties());
} else if (ySuspect.getTags().contains(TAG__NUMBER)) {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYNumericField();
} else if (ySuspect.getTags().contains(TAG__DATE)) {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYDateTime();
for (Entry<String, String> prop : ySuspect.getProperties()) {
if (YDateTimeFormat.get(prop.getKey().toUpperCase()) != null) {
YDateTimeDatatype yDt = ExtDatatypesFactory.eINSTANCE.createYDateTimeDatatype();
yDt.setFormat(YDateTimeFormat.get(prop.getKey().toUpperCase()));
if (YDateTimeResolution.get(prop.getValue().toUpperCase()) != null) {
yDt.setResolution(YDateTimeResolution.get(prop.getValue().toUpperCase()));
}
((YDateTime) yEmbeddable).setDatatype(yDt);
// we found a format - ignore the rest if any
break;
}
}
} else if (ySuspect.getTags().contains(TAG__BOOLEAN)) {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYCheckBox();
} else if (ySuspect.getTags().contains(TAG__BLOB)) {
yEmbeddable = createYBlobUploadComponent(ySuspect);
} else if (ySuspect.getTags().contains(TAG__GRID)) {
yEmbeddable = createGrid(ySuspect);
} else if (ySuspect.getTags().contains(TAG__BEAN_REFERENCE)) {
yEmbeddable = createYBeanReference(ySuspect);
} else if (ySuspect.getTags().contains(TAG__TABLE)) {
yEmbeddable = createTable(ySuspect);
} else if (ySuspect.getTags().contains(TAG__ENUM_OPTIONS)) {
yEmbeddable = createEnumOptions(ySuspect);
} else if (ySuspect.getTags().contains(TAG__ENUM_COMBO)) {
yEmbeddable = createEnumCombo(ySuspect);
} else if (ySuspect.getTags().contains(TAG__RICH_TEXT__STRING)) {
yEmbeddable = createRichTextFieldString(ySuspect);
} else if (ySuspect.getTags().contains(TAG__MASKED_TEXT_FIELD)) {
yEmbeddable = createMaskedTextField(ySuspect);
} else if (ySuspect.getTags().contains(TAG__MASKED_DECIMAL_FIELD)) {
yEmbeddable = createMaskedDecimalField(ySuspect);
} else if (ySuspect.getTags().contains(TAG__RICH_TEXT__BLOB)) {
yEmbeddable = createRichTextFieldBlob(ySuspect);
suspectInfo.getTags().add(TAG__RICH_TEXT__BLOB);
} else if (ySuspect.getTags().contains(TAG__ORGANIZATION_COMBO)) {
yEmbeddable = createOrganizationCombo(ySuspect);
} else if (ySuspect.getTags().contains(TAG__PERSPECTIVE_COMBO)) {
yEmbeddable = createPerspectiveCombo(ySuspect);
} else if (ySuspect.getTags().contains(TAG__THEME_COMBO)) {
yEmbeddable = createThemeCombo(ySuspect);
} else if (ySuspect.getTags().contains(TAG__IMAGE_PICKER)) {
yEmbeddable = createIconComboBox(ySuspect);
} else if (ySuspect.getTags().contains(TAG__SUBTYPES_ROOT)) {
createSubTypeElements((YSubTypeBaseSuspect) ySuspect);
} else if (ySuspect.getTags().contains(TAG__DTO)) {
createNestedBeanElements((YTypedCompoundSuspect) ySuspect);
} else {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYTextField();
}
if (yEmbeddable != null) {
yEmbeddable.setLabelI18nKey(ySuspect.getLabelI18nKey());
yEmbeddable.setLabel(ySuspect.getLabel());
yEmbeddable.setId(ySuspect.getId());
yEmbeddable.setCssClass(EnumCssClass.BOX.styleName());
suspectInfo.setTarget(yEmbeddable);
if(ySuspect.getTags().contains(TAG__ON_KANBAN_CARD)){
yEmbeddable.getTags().add(TAG__ON_KANBAN_CARD);
}
// --- Required for validation ---
if (ySuspect.getTags().contains(TAG__CONSTRAINT)) {
if (yEmbeddable instanceof YField) {
YBeanValidationValidator validator = ValidationFactory.eINSTANCE.createYBeanValidationValidator();
validator.setBvalClassFullyQualifiedName(ySuspect.getProperties().get(PROPERTY_CLASS));
validator.setBvalProperty(ySuspect.getProperties().get(PROPERTY_NAME));
((YField) yEmbeddable).getValidators().add(validator);
}
}
if (ySuspect.getTags().contains(TAG__UNIQUE)) {
if (yEmbeddable instanceof YField) {
YUniqueAttributeValidator validator = ValidationFactory.eINSTANCE.createYUniqueAttributeValidator();
validator.setValTypeFullyQualifiedName(ySuspect.getProperties().get(PROPERTY_CLASS));
validator.setPropertyPath(ySuspect.getProperties().get(PROPERTY_NAME));
// this endpoint gains access to the bound bean
validator.setContainerValueBindingEndpoint(EcoreUtil.copy(ySuspect.getContainerValueBindingEndpoint()));
((YField) yEmbeddable).getValidators().add(validator);
}
}
// ------------------------------
// Only for Test purposes
// Test Converter
if (ySuspect.getTags().contains("FloatToUomo")) {
((YNumericField) yEmbeddable).setConverter(YConverterFactory.eINSTANCE.createYNumericToUomoConverter());
}
// prepares the value bindings
prepareValueBindings(suspectInfo, yEmbeddable);
// required step to enable the permissions managed by the visibility
// processors
yEmbeddable.setAuthorizationGroup(ySuspect.getAuthorizationGroup());
yEmbeddable.setAuthorizationId(ySuspect.getAuthorizationId());
}
return yEmbeddable;
}
/**
* Helper method to find out if the suspect properties keys contains a function normalizer entry
*
* @param ySuspect
* @return
*/
private boolean existFunctionsInProperties(YSuspect ySuspect) {
for (FunctionType functionType : functionTypingApi.getTypes()) {
if (existInProperties(ySuspect, functionType.getName().toLowerCase())) {
return true;
}
}
return false;
}
/**
* Creates the icon combo box.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createIconComboBox(YSuspect ySuspect) {
YTypedSuspect yTypedSuspect = (YTypedSuspect) ySuspect;
YIconComboBox yIconCombo = YECviewFactory.eINSTANCE.createYIconComboBox();
yIconCombo.setType(yTypedSuspect.getType());
yIconCombo.setTypeQualifiedName(yTypedSuspect.getTypeQualifiedName());
// AVOID to use the origin properties map into the addAll-Method!!!!!
// Afterwards the content of ySuspect.getProperties() is EMPTY!!!!
// Don´t think even to clone the properties EMap. Same result.
// Preferred way is as follows.
EMap<String, String> yEmbeddableProps = yIconCombo.getProperties();
for (Entry<String, String> prop : ySuspect.getProperties()) {
yEmbeddableProps.put(prop.getKey(), prop.getValue());
}
return yIconCombo;
}
/**
* Creates elements for a dtos subtype.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createSubTypeElements(YSubTypeBaseSuspect ySuspect) {
for (YSuspect temp : ySuspect.getChildren()) {
YSubTypeSuspect childSuspect = (YSubTypeSuspect) temp;
YDetailBeanSlot beanSlot = (YDetailBeanSlot) childSuspect.getBeanSlot();
for (YSuspect suspect : childSuspect.getChildren()) {
// Create a new suspect info.
YSuspectInfo suspectInfo = layoutingInfo.createSuspectInfo(suspect);
// add the suspectInfo as active suspect
layoutingInfo.getActiveSuspectInfos().add(suspectInfo);
YEmbeddable yEmbeddable = prepareElementForSuspect(suspectInfo);
addElement(null, yEmbeddable, suspectInfo);
// create VP
// we are using the master beanslot for it. The subtypeSlot will
// only be invoked, if the type matches the type of the
// beanslot.
// but for visible=false we also need a not type-matching dto
suspectInfo.getVisibilityProcessors().add(createSubTypeVisibilityProcessor(yEmbeddable, childSuspect, beanSlot.getMasterBeanSlot()));
}
}
return null;
}
/**
* Creates elements for nested types in the dto.
*
* @param ySuspect
* the y suspect
* @return the yEmbeddable
*/
private YEmbeddable createNestedBeanElements(YTypedCompoundSuspect ySuspect) {
for (YSuspect childSuspect : ySuspect.getChildren()) {
// Create a new suspect info.
YSuspectInfo suspectInfo = layoutingInfo.createSuspectInfo(childSuspect);
// add the suspectInfo as active suspect
layoutingInfo.getActiveSuspectInfos().add(suspectInfo);
YEmbeddable yEmbeddable = prepareElementForSuspect(suspectInfo);
addElement(null, yEmbeddable, suspectInfo);
}
return null;
}
/**
* Create a VP which reacts to the type of the value in the beanslot. And matches it against the type of the child suspect.
*
* @param yEmbeddable
*
* @param childSuspect
* @param beanSlot
*
* @return the vp
*/
private YSubTypeVisibilityProcessor createSubTypeVisibilityProcessor(YEmbeddable yEmbeddable, YSubTypeSuspect childSuspect, YBeanSlot beanSlot) {
// create a VP which sets the element visible true/false if the
// type of the bound dto matches the expected or not
YSubTypeVisibilityProcessor yVp = YVisibilityFactory.eINSTANCE.createYSubTypeVisibilityProcessor();
yVp.setType(childSuspect.getType());
yVp.setTypeQualifiedName(childSuspect.getTypeQualifiedName());
yVp.setTarget(yEmbeddable);
// the binding endpoint for the slot
YBeanSlotValueBindingEndpoint slotEP = beanSlot.createBindingEndpoint("");
// the binding endpoint for the vp
YVisibilityProcessorValueBindingEndpoint vbEndpoint = BindingFactory.eINSTANCE.createYVisibilityProcessorValueBindingEndpoint();
vbEndpoint.setProperty("input");
YValueBinding yBinding = BindingFactory.eINSTANCE.createYValueBinding();
yBinding.setModelEndpoint(slotEP);
yBinding.setTargetEndpoint(vbEndpoint);
yBinding.setModelToTargetStrategy(YBindingUpdateStrategy.UPDATE);
yBinding.setTargetToModelStrategy(YBindingUpdateStrategy.NEVER);
yVp.getDataUsed().add(yBinding);
return yVp;
}
/**
* Creates the y blob upload component.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
// Helper Methods
private YEmbeddable createYBlobUploadComponent(YSuspect ySuspect) {
YEmbeddable yEmbeddable = YECviewFactory.eINSTANCE.createYBlobUploadComponent();
if (existInProperties(ySuspect, PROPERTY_BLOB)) {
try {
((YBlobUploadComponent) yEmbeddable).setDisplayResolutionId(Integer.parseInt(ySuspect.getProperties().get(PROPERTY_BLOB)));
} catch (NumberFormatException nfe) {
// TODO (JCD): ExceptionHandling
LOGGER.error("blob property is not from type int!");
}
if (existInProperties(ySuspect, PROPERTY_BLOB_FIRMLY_LINKED)) {
((YBlobUploadComponent) yEmbeddable).setFirmlyLinked(true);
}
if (existInProperties(ySuspect, PROPERTY_BLOB_UNIQUE_NAMED)) {
((YBlobUploadComponent) yEmbeddable).setUniqueNameEnabled(true);
}
}
return yEmbeddable;
}
/**
* Creates a new {@link YRichTextArea} and configures it to use blob binding. See {@link YRichTextArea#createBlobValueEndpoint()}.
*
* @param ySuspect
* @return
*/
private YEmbeddable createRichTextFieldBlob(YSuspect ySuspect) {
YRichTextArea yRichText = YECviewFactory.eINSTANCE.createYRichTextArea();
yRichText.setUseBlob(true);
return yRichText;
}
/**
* Creates a new {@link YRichTextArea} and configures it to use blob binding. See {@link YRichTextArea#createValueEndpoint()}.
*
* @param ySuspect
* @return
*/
private YEmbeddable createRichTextFieldString(YSuspect ySuspect) {
YRichTextArea yRichText = YECviewFactory.eINSTANCE.createYRichTextArea();
yRichText.setUseBlob(false);
return yRichText;
}
/**
* Creates a new {@link YMaskedTextField}.
*
* @param ySuspect
* @return
*/
private YEmbeddable createMaskedTextField(YSuspect ySuspect) {
YMaskedTextField yRichText = YECviewFactory.eINSTANCE.createYMaskedTextField();
yRichText.setMask(ySuspect.getProperties().get(ILayoutingStrategy.PROPERTY_MASK));
return yRichText;
}
/**
* Creates a new {@link YMaskedDecimalField}.
*
* @param ySuspect
* @return
*/
private YEmbeddable createMaskedDecimalField(YSuspect ySuspect) {
YMaskedDecimalField yRichText = YECviewFactory.eINSTANCE.createYMaskedDecimalField();
yRichText.setMask(ySuspect.getProperties().get(ILayoutingStrategy.PROPERTY_MASK));
return yRichText;
}
/**
* Creates a new {@link YPasswordField} and configures it to use blob binding. See {@link YPasswordField#createValueEndpoint()}.
*
* @param ySuspect
* @return
*/
private YEmbeddable createPasswordField(YSuspect ySuspect) {
YPasswordField yPasswordField = ExtensionModelFactory.eINSTANCE.createYPasswordField();
return yPasswordField;
}
/**
* Creates the y bean reference.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createYBeanReference(YSuspect ySuspect) {
YTypedSuspect yTypedSuspect = (YTypedSuspect) ySuspect;
EMap<String, String> suspectProperties = yTypedSuspect.getProperties();
YEmbeddable yEmbeddable = null;
if (isEditable(ySuspect)) {
if (suspectProperties.containsKey(ILayoutingStrategy.PROPERTY__ITEM_CAPTION)) {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYBeanReferenceField();
YBeanReferenceField beanReferenceField = (YBeanReferenceField) yEmbeddable;
beanReferenceField.setType(yTypedSuspect.getType());
beanReferenceField.setTypeQualifiedName(yTypedSuspect.getTypeQualifiedName());
beanReferenceField.setCaptionPropertyPath(getCaptionPropertyPath(suspectProperties));
// create search dialog
Class<?> type = yTypedSuspect.getType();
YFilteringComponent yFilterComponent = ExtensionModelFactory.eINSTANCE.createYFilteringComponent();
String filterDepthString = suspectProperties.get(ILayoutingStrategy.PROPERTY__FILTER_DEPTH);
int depth = 0;
if (filterDepthString != null) {
depth = Integer.valueOf(filterDepthString);
}
ECViewUtil.fill(type, depth, yFilterComponent);
if (!yFilterComponent.getFilterDescriptors().isEmpty()) {
beanReferenceField.setFilteringComponent(yFilterComponent);
}
}
// Alternative for non editable bean references is a non editable
// Textfield.
} else {
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYTextField();
for (YBindingEndpoint vEndPoint : yTypedSuspect.getValueBindingEndpoints()) {
if (vEndPoint instanceof YDetailValueBindingEndpoint) {
YDetailValueBindingEndpoint detailedVEndpoint = (YDetailValueBindingEndpoint) vEndPoint;
detailedVEndpoint.setPropertyPath(detailedVEndpoint.getPropertyPath().concat(".").concat(getCaptionPropertyPath(suspectProperties)));
}
}
yTypedSuspect.setId(ySuspect.getId().concat(".").concat(yTypedSuspect.getTypeQualifiedName()).concat(".").concat(getCaptionPropertyPath(suspectProperties)));
yTypedSuspect.setTypeQualifiedName(String.class.getCanonicalName());
yTypedSuspect.setType(String.class);
}
// TODO: check if yEmbeddable might be set by some other condition.
// Otherwise it might be null.
return yEmbeddable;
}
private String getCaptionPropertyPath(EMap<String, String> suspectProperties) {
String captionPropertyPath = suspectProperties.get(ILayoutingStrategy.PROPERTY__ITEM_CAPTION);
if (captionPropertyPath == null || captionPropertyPath.isEmpty()) {
captionPropertyPath = suspectProperties.get(ILayoutingStrategy.PROPERTY__ITEM_DESCRIPTION);
}
return captionPropertyPath;
}
/**
* Creates the table.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createTable(YSuspect ySuspect) {
YEmbeddable yEmbeddable;
YCollectionSuspect yCollectionSuspect = (YCollectionSuspect) ySuspect;
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYTable();
YTable table = (YTable) yEmbeddable;
table.setType(yCollectionSuspect.getType());
table.setTypeQualifiedName(yCollectionSuspect.getTypeQualifiedName());
table.setUseBeanService(false);
EList<YColumn> columns = table.getColumns();
for (YColumnInfo columnInfo : yCollectionSuspect.getColumns()) {
YColumn column = ExtensionModelFactoryImpl.eINSTANCE.createYColumn();
column.setPropertyPath(columnInfo.getName());
column.setLabel(columnInfo.getName());
column.setType(columnInfo.getType());
column.setTypeQualifiedName(columnInfo.getTypeQualifiedName());
column.setConverter(getConverter(columnInfo.getProperties()));
YDatadescription datadescription = DatatypesFactoryImpl.eINSTANCE.createYDatadescription();
datadescription.setLabelI18nKey(columnInfo.getLabelI18nKey());
column.setDatadescription(datadescription);
if (columnInfo.getProperties() != null && !columnInfo.getProperties().isEmpty()) {
column.getProperties().addAll(columnInfo.getProperties());
}
columns.add(column);
}
for (YColumn yColumn : table.getColumns()) {
yColumn.setVisible(true);
}
return yEmbeddable;
}
/**
* Creates the grid.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createGrid(YSuspect ySuspect) {
YEmbeddable yEmbeddable;
YCollectionSuspect yTypedSuspect = (YCollectionSuspect) ySuspect;
GridFactory gFactory = new GridFactory();
CxGrid grid = gFactory.createGrid(yTypedSuspect);
grid = CxGridUtil.setPermissions(userAccessService, grid);
yEmbeddable = grid;
return yEmbeddable;
}
/**
* Creates the enum options.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createEnumOptions(YSuspect ySuspect) {
YEmbeddable yEmbeddable;
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYEnumOptionsGroup();
YEnumOptionsGroup enumOptionsGroup = (YEnumOptionsGroup) yEmbeddable;
YTypedSuspect yTypedSuspect = (YTypedSuspect) ySuspect;
enumOptionsGroup.setType(yTypedSuspect.getType());
enumOptionsGroup.setTypeQualifiedName(yTypedSuspect.getTypeQualifiedName());
return yEmbeddable;
}
/**
* Creates the enum combo boxes.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createEnumCombo(YSuspect ySuspect) {
YEmbeddable yEmbeddable;
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYEnumComboBox();
YEnumComboBox yEnumCombo = (YEnumComboBox) yEmbeddable;
YTypedSuspect yTypedSuspect = (YTypedSuspect) ySuspect;
yEnumCombo.setType(yTypedSuspect.getType());
yEnumCombo.setTypeQualifiedName(yTypedSuspect.getTypeQualifiedName());
return yEmbeddable;
}
/**
* Creates the organization combo box inclosing organization positions.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createOrganizationCombo(YSuspect ySuspect) {
YEmbeddable yEmbeddable;
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYComboBox();
YComboBox yCombo = (YComboBox) yEmbeddable;
yCombo.setUseBeanService(false);
YTypedSuspect yTypedSuspect = (YTypedSuspect) ySuspect;
yCombo.setType(yTypedSuspect.getType());
yCombo.setTypeQualifiedName(yTypedSuspect.getTypeQualifiedName());
Collection<String> positionNames = getOrganizationPositionNames(ProductConfiguration.getAuthenticationOrganizationId());
if (positionNames.isEmpty()) {
yCombo.getCollection().add(IUserAccessService.ADMINISTRATOR);
yCombo.setSelection(IUserAccessService.ADMINISTRATOR);
yCombo.setEditable(false);
} else {
yCombo.getCollection().addAll(getOrganizationPositionNames(ProductConfiguration.getAuthenticationOrganizationId()));
}
return yEmbeddable;
}
/**
* Creates the perspective combo box inclosing perspectives.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createPerspectiveCombo(YSuspect ySuspect) {
YEmbeddable yEmbeddable;
yEmbeddable = YECviewFactory.eINSTANCE.createYPairComboBox();
YPairComboBox yCombo = (YPairComboBox) yEmbeddable;
yCombo.setUseBeanService(false);
yCombo.setType(Pair.class);
yCombo.setTypeQualifiedName(Pair.class.getCanonicalName());
yCombo.getCollection().addAll(getPerspectiveNames());
yCombo.setCaptionProperty("first");
return yEmbeddable;
}
/**
* Creates the theme combo box inclosing themes.
*
* @param ySuspect
* the y suspect
* @return the y embeddable
*/
private YEmbeddable createThemeCombo(YSuspect ySuspect) {
YEmbeddable yEmbeddable;
yEmbeddable = ExtensionModelFactory.eINSTANCE.createYComboBox();
YComboBox yCombo = (YComboBox) yEmbeddable;
yCombo.setUseBeanService(false);
yCombo.setCaptionProperty("label");
yCombo.setType(VaaclipseUiTheme.class);
yCombo.setTypeQualifiedName(VaaclipseUiTheme.class.getCanonicalName());
yCombo.setModelSelectionType(String.class);
yCombo.setModelSelectionTypeQualifiedName(String.class.getCanonicalName());
yCombo.getCollection().addAll(getThemes());
YConverter conv = YConverterFactory.eINSTANCE.createYVaaclipseUiThemeToStringConverter();
yCombo.setConverter(conv);
return yEmbeddable;
}
private Collection<String> getOrganizationPositionNames(String organizationName) {
IOrganizationService organizationService = ServiceListener.getOrganizationService();
// In case of the open source solution a organization service is not
// available!
if (organizationService != null) {
AbstractSubOrganization organization = organizationService.getOrganization(organizationName);
if (organization != null) {
Collection<String> positionNames = new TreeSet<>();
for (IPosition position : organization.getPositions()) {
positionNames.add(position.getLinkAlias());
}
return positionNames;
}
}
return Collections.emptyList();
}
@SuppressWarnings("rawtypes")
private Collection<Pair> getPerspectiveNames() {
return dslMetadataService.getDslGrammarElementNames(IDSLMetadataService.DSLLiterals.PERSPECTIVES);
}
private Set<VaaclipseUiTheme> getThemes() {
return VaaclipseUiTheme.values(ThemeList.forProduct);
}
/**
* Sets the custom decimal converter.
*
* @param yEmbeddable
* the y embeddable
* @param ySuspect
* the y suspect
*/
private void setCustomDecimalConverter(YEmbeddable yEmbeddable, YSuspect ySuspect) {
if (existFunctionsInProperties(ySuspect)) {
YCustomDecimalConverter converter = YConverterFactory.eINSTANCE.createYCustomDecimalConverter();
converter.getProperties().addAll(ySuspect.getProperties());
((YCustomDecimalField) yEmbeddable).setConverter(converter);
}
}
/**
* Checks if is tab sheet needed.
*
* @param suspects
* the suspects
* @return true, if is tab sheet needed
*/
private boolean isTabSheetNeeded(EList<YSuspect> suspects) {
for (YSuspect suspect : suspects) {
if (suspect.getTags().contains(TAG__TABLE) || suspect.getTags().contains(TAG__GRID)) {
return true;
}
}
return false;
}
/**
* Checks for existing supect property
*/
private boolean existInProperties(YElement ySuspect, String propConstant) {
if (!ySuspect.getProperties().isEmpty()) {
String propertyValue = ySuspect.getProperties().get(propConstant);
if (propertyValue != null) {
return true;
}
}
return false;
}
/**
* Gets the converter.
*
* @param properties
* the properties
* @return the converter
*/
public static YConverter getConverter(EMap<String, String> properties) {
String decimalformatPropertyValue = properties.get(PROPERTY_DECIMALFORMAT);
if (decimalformatPropertyValue != null) {
YSimpleDecimalConverter yConverter = YConverterFactory.eINSTANCE.createYSimpleDecimalConverter();
yConverter.setNumberFormatPattern(decimalformatPropertyValue);
return yConverter;
} else {
return null;
}
}
/**
* Helper class to determine if the component is editable due to the existing user permissions
*/
private boolean isEditable(YSuspect ySuspect) {
String dtoName = ySuspect.getAuthorizationGroup();
String dtoProperty = ySuspect.getAuthorizationId();
if (userAccessService.isGranted(Group.DTO, Action.READABLE, dtoName)) {
boolean invisible = userAccessService.isVetoed(Group.DTO, Action.INVISIBLE, dtoName, dtoProperty);
if (!invisible) {
boolean enabled = !userAccessService.isVetoed(Group.DTO, Action.DISABLED, dtoName, dtoProperty);
boolean editable = !userAccessService.isVetoed(Group.DTO, Action.NONEDITABLE, dtoName, dtoProperty);
if (enabled && editable) {
return true;
}
}
}
return false;
}
/**
* Gets the entity i18n key.
*
* @param suspects
* the suspects
* @return the entity i18n key
*/
private String getEntityI18nKey(EList<YSuspect> suspects) {
for (YSuspect suspect : suspects) {
String dto = suspect.getAuthorizationGroup();
return NamingConventionsUtil.toSimpleEntityName(dto);
}
return "";
}
/**
* Helper Comparator to allow to sort a list of suspects due to their table or grid property value. Sort criteria is that the highest value became the first of the list
* followed by the suspects with decreasing value. In case of same values the order between the compared suspects will be maintained and in case of no value the suspect gets
* the value 0 and became the last elements of the list.
*
* @author Jose C. Dominguez
*
*/
class SuspectComparator implements Comparator<YSuspect> {
/*
* (non-Javadoc)
*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@Override
public int compare(YSuspect suspect1, YSuspect suspect2) {
if (suspect1 == null && suspect2 == null) {
return 0;
} else if (suspect1 == null) { // && suspect2 != null
return (-1);
} else if (suspect2 == null) { // suspect1 != null &&
return 1;
} else { // this means: (suspect1 != null && suspect2 != null)
boolean lessThan = getValue(suspect1).compareTo(getValue(suspect2)) < 0;
if (lessThan) {
return 1;
} else {
boolean greaterThan = getValue(suspect1).compareTo(getValue(suspect2)) > 0;
if (greaterThan) {
return (-1);
} else {
return 0;
}
}
}
}
/**
* Gets the value.
*
* @param suspect
* the suspect
* @return the value
*/
private Integer getValue(YSuspect suspect) {
try {
String value = suspect.getProperties().get(PROPERTY_TABLE);
if (value == null) {
value = suspect.getProperties().get(PROPERTY_GRID);
}
return Integer.valueOf(value);
} catch (NumberFormatException nfe) {
return 0;
}
}
}
}