| /** |
| * |
| * 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: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| * |
| * This copyright notice shows up in the generated Java code |
| * |
| */ |
| package org.eclipse.osbp.autowirehelper |
| |
| import com.google.inject.Inject |
| import com.google.inject.Injector |
| import java.util.Collection |
| import java.util.LinkedList |
| import java.util.List |
| import java.util.Map |
| import java.util.Set |
| import java.util.Stack |
| import javax.validation.Valid |
| import org.eclipse.emf.common.util.URI |
| import org.eclipse.emf.ecore.EObject |
| import org.eclipse.emf.ecore.InternalEObject |
| import org.eclipse.emf.ecore.resource.Resource |
| import org.eclipse.emf.ecore.resource.ResourceSet |
| import org.eclipse.emf.ecore.util.EcoreUtil |
| import org.eclipse.osbp.autowirehelper.utils.AutowireUtil |
| import org.eclipse.osbp.dsl.common.datatypes.IDto |
| import org.eclipse.osbp.ecview.core.common.model.binding.BindingFactory |
| 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.YECViewModelListBindingEndpoint |
| import org.eclipse.osbp.ecview.core.common.model.binding.YListBindingEndpoint |
| import org.eclipse.osbp.ecview.core.common.model.binding.YValueBindingEndpoint |
| import org.eclipse.osbp.ecview.core.common.model.core.YAlignment |
| import org.eclipse.osbp.ecview.core.common.model.core.YAlignmentContainer |
| import org.eclipse.osbp.ecview.core.common.model.core.YAuthorizationable |
| import org.eclipse.osbp.ecview.core.common.model.core.YBeanSlot |
| import org.eclipse.osbp.ecview.core.common.model.core.YBeanSlotListBindingEndpoint |
| import org.eclipse.osbp.ecview.core.common.model.core.YDetailBeanSlot |
| import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddable |
| import org.eclipse.osbp.ecview.core.common.model.core.YLayout |
| import org.eclipse.osbp.ecview.core.common.model.core.YView |
| import org.eclipse.osbp.ecview.core.^extension.model.^extension.util.SimpleExtensionModelFactory |
| import org.eclipse.osbp.ecview.dsl.autowire.IAutowireDelegate |
| import org.eclipse.osbp.ecview.dsl.derivedstate.UiModelDerivedStateComputerx |
| import org.eclipse.osbp.ecview.dsl.extensions.BeanHelper |
| import org.eclipse.osbp.ecview.dsl.extensions.BindableTypeResolver |
| import org.eclipse.osbp.ecview.dsl.extensions.BindingInfoHelper |
| import org.eclipse.osbp.ecview.dsl.extensions.BindingInfoHelper.BindingInfo |
| import org.eclipse.osbp.ecview.dsl.extensions.OperationExtensions |
| import org.eclipse.osbp.ecview.dsl.extensions.OperationExtensions.OperationInfo |
| import org.eclipse.osbp.ecview.dsl.extensions.SuperTypeCollector |
| import org.eclipse.osbp.ecview.dsl.extensions.TypeHelper |
| import org.eclipse.osbp.ecview.^extension.api.ILayoutingStrategy |
| import org.eclipse.osbp.ecview.^extension.model.YColumnInfo |
| import org.eclipse.osbp.ecview.^extension.model.YECviewFactory |
| import org.eclipse.osbp.ecview.^extension.model.YStrategyLayout |
| import org.eclipse.osbp.ecview.^extension.model.YSubTypeSuspect |
| import org.eclipse.osbp.ecview.^extension.model.YSuspect |
| import org.eclipse.osbp.ecview.^extension.model.YTypedCompoundSuspect |
| import org.eclipse.osbp.ecview.^extension.model.YTypedSuspect |
| import org.eclipse.osbp.ecview.^extension.model.visibility.YVisibilityFactory |
| import org.eclipse.osbp.ecview.semantic.uimodel.UiBeanSlot |
| import org.eclipse.osbp.ecview.semantic.uimodel.UiBindingEndpointAssignment |
| import org.eclipse.osbp.ecview.semantic.uimodel.UiEmbeddable |
| import org.eclipse.osbp.ecview.semantic.uimodel.UiHorizontalLayout |
| import org.eclipse.osbp.ecview.semantic.uimodel.UiLayout |
| import org.eclipse.osbp.mobile.vaadin.ecview.model.VMVerticalComponentGroup |
| import org.eclipse.osbp.mobile.vaadin.ecview.model.VaadinMobileFactory |
| import org.eclipse.osbp.runtime.common.annotations.DomainDescription |
| import org.eclipse.osbp.runtime.common.annotations.DomainKey |
| import org.eclipse.osbp.runtime.common.annotations.FilterDepth |
| import org.eclipse.osbp.runtime.common.annotations.UniqueEntry |
| import org.eclipse.osbp.runtime.common.metric.TimeLogger |
| import org.eclipse.osbp.utils.functionnormalizer.api.FunctionTypingAPI |
| import org.eclipse.xtext.common.types.JvmDeclaredType |
| import org.eclipse.xtext.common.types.JvmGenericType |
| import org.eclipse.xtext.common.types.JvmParameterizedTypeReference |
| import org.eclipse.xtext.common.types.JvmPrimitiveType |
| import org.eclipse.xtext.common.types.JvmType |
| import org.eclipse.xtext.common.types.JvmTypeReference |
| import org.eclipse.xtext.common.types.TypesFactory |
| import org.eclipse.xtext.common.types.TypesPackage |
| import org.eclipse.xtext.naming.IQualifiedNameProvider |
| import org.eclipse.xtext.resource.IReferenceDescription |
| import org.eclipse.xtext.ui.editor.findrefs.IReferenceFinder |
| import org.eclipse.xtext.util.IAcceptor |
| import org.eclipse.xtext.util.concurrent.IUnitOfWork |
| import org.eclipse.osbp.runtime.common.annotations.OnKanbanCard |
| |
| @SuppressWarnings("restriction") |
| class AutowireHelper implements IAutowireDelegate { |
| |
| @Inject extension TypeHelper |
| @Inject extension AutowireUtil |
| @Inject extension IQualifiedNameProvider |
| @Inject BindingInfoHelper bindingInfoHelper; |
| @Inject |
| private IReferenceFinder referenceFinder; |
| @Inject |
| private Injector injector |
| |
| private VaadinMobileFactory vFactory = VaadinMobileFactory.eINSTANCE |
| |
| UiModelDerivedStateComputerx computer |
| boolean mobile |
| |
| YLayout yLayout |
| UiLayout uiLayout |
| |
| Layouter layouter |
| |
| JvmDeclaredType beanType |
| |
| final SimpleExtensionModelFactory factory = new SimpleExtensionModelFactory |
| |
| YView yView |
| |
| YBeanSlot yMainBeanslot |
| |
| override autowire(UiLayout uiLayout, UiModelDerivedStateComputerx computer, boolean mobile) { |
| if (!uiLayout.autowire) { |
| return |
| } |
| |
| val logger = TimeLogger.start(typeof(AutowireHelper)) |
| |
| this.computer = computer; |
| this.mobile = mobile; |
| |
| this.uiLayout = uiLayout; |
| this.yLayout = computer.associatedUi(uiLayout) |
| this.yView = yLayout.view |
| this.yMainBeanslot = getBeanSlot(uiLayout) |
| switch (uiLayout) { |
| UiHorizontalLayout: { |
| layouter = if(!mobile) new StrategyLayoutLayouter else new MobileLayouter |
| layouter.setup(uiLayout, yLayout) |
| } |
| default: |
| return |
| } |
| |
| // val userAccessService = UserServiceBinder.getUserAccessService |
| // val userName = userAccessService.user.userName |
| // val permissionList = userAccessService.findPermissionsForUser(userName) |
| // for (permission : permissionList.permissions){ |
| // println(permission) |
| // } |
| val BindableTypeResolver resolver = new BindableTypeResolver |
| var resolvedType = resolver.resolveType(uiLayout.autoWireSource) |
| if (resolvedType instanceof JvmDeclaredType) { |
| beanType = resolvedType as JvmDeclaredType |
| |
| // Gets the operation infos for the given type in form of a map |
| val opInfoMap = OperationExtensions.getOperationInfos(beanType) |
| |
| // operation info map sorted in a list |
| val sortedOpInfoMapList = createSortedMapList(opInfoMap) |
| |
| // creates the a suspect structure based on the operation infos |
| sortedOpInfoMapList.createSuspectStructure(beanType, mobile, null) |
| |
| } |
| |
| } |
| |
| /** |
| * Finds all sub types of the beanType |
| */ |
| def findSubTypes(JvmType dtoType, Resource resource) { |
| val Set<URI> result = newHashSet() |
| val Set<URI> jvmTypeURIs = newHashSet() |
| jvmTypeURIs += EcoreUtil.getURI(dtoType) |
| val IAcceptor<IReferenceDescription> acceptor = [ |
| val IReferenceDescription desc = it |
| if (desc.EReference === TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE) { |
| if (sourceEObjectUri.fragment.endsWith("/@superTypes.0")) { |
| val URI uri = desc.sourceEObjectUri; |
| result += URI.createURI(uri.toString.replace("/@superTypes.0", "")) |
| } |
| } |
| ] |
| referenceFinder.findAllReferences(jvmTypeURIs, new LocalResourceAccess(resource.resourceSet), acceptor, null) |
| result |
| } |
| |
| def YBeanSlot getBeanSlot(UiLayout uiLayout) { |
| var autoWireSourceTemp = uiLayout.autoWireSource |
| if (autoWireSourceTemp instanceof UiBindingEndpointAssignment) { |
| var alias = (autoWireSourceTemp as UiBindingEndpointAssignment).typedBindableAlias |
| if (alias instanceof UiBeanSlot) { |
| return computer.associatedUi(alias as UiBeanSlot) |
| } |
| } |
| return null |
| } |
| |
| def createSuspectStructure(JvmDeclaredType type, boolean mobile, YTypedCompoundSuspect parentSuspect) { |
| |
| // Gets the operation infos for the given type in form of a map |
| val opInfoMap = OperationExtensions.getOperationInfos(type) |
| |
| // operation info map sorted in a list |
| val sortedOpInfoMapList = createSortedMapList(opInfoMap) |
| |
| sortedOpInfoMapList.createSuspectStructure(type, mobile, parentSuspect) |
| } |
| |
| def createSuspectStructure(LinkedList<Map<String, OperationInfo>> sortedOpInfoMapList, JvmDeclaredType dtoType, |
| boolean mobile, YTypedCompoundSuspect parentSuspect) { |
| if (!dtoType.isEnum) { |
| sortedOpInfoMapList.forEach [ |
| it.createSuspectStructure(dtoType, mobile, parentSuspect) |
| ] |
| } |
| |
| // lets create a new suspect in form of a tree to add the sub types to it |
| val subTypeURIs = findSubTypes(dtoType, uiLayout.eResource) |
| if (!subTypeURIs.empty) { |
| val subtypeRootSuspect = YECviewFactory.eINSTANCE.createYSubTypeBaseSuspect |
| subtypeRootSuspect.tags += ILayoutingStrategy.TAG__SUBTYPES_ROOT |
| |
| // TODO load the class |
| subtypeRootSuspect.typeQualifiedName = dtoType.qualifiedName |
| layouter.add(subtypeRootSuspect) |
| layouter.pushHierarchy(subtypeRootSuspect) |
| } |
| subTypeURIs.forEach [ |
| val JvmDeclaredType subDtoJvmType = uiLayout.eResource.resourceSet.getEObject(it, true) as JvmDeclaredType |
| subDtoJvmType.createSubTypeDtoSuspect() |
| ] |
| if (!subTypeURIs.empty) { |
| layouter.popHierarchy |
| } |
| } |
| |
| def createSuspectStructure(Map<String, OperationInfo> opInfoMap, JvmDeclaredType dtoType, boolean mobile, |
| YTypedCompoundSuspect parentSuspect) { |
| |
| opInfoMap.values.forEach [ |
| var JvmType type = null |
| try { |
| type = getter.returnType.type |
| } catch (NullPointerException e) { |
| return |
| } |
| var YSuspect suspect |
| var properties = newArrayList() |
| if (it.field !== null) { |
| properties.addAll(dtoType.toProperties(it.field.declaringType.qualifiedName + "." + it.name)) |
| } |
| if (type.boolean && !it.isDirtyMark) { |
| if(mobile) type.createMobileSwitch(it) else suspect = type.createCheckbox(it) |
| } else if (type.numberWithDigits) { |
| suspect = type.createDecimalField(it) |
| if (dtoType.isAttribute(it.name, "NumberToUomo")) { |
| suspect.tags += "NumberToUomo" |
| } else { |
| var dataType = dtoType.toDataType(it.name) |
| if (dataType !== null) { |
| var dataTypeName = dataType.jvmTypeReference.type.identifier |
| if (dataTypeName.equals(Double.canonicalName)) { |
| suspect = type.createCustomDecimalField(it) |
| } |
| } |
| } |
| } else if (type.numberWithoutDigits) { |
| |
| if (!it.idOrUUID && !it.version && !it.dirtyMark) { |
| suspect = type.createNumberField(it) |
| } |
| } else if (type.string) { |
| val fieldType = properties.findFirst[it.key.equals(ILayoutingStrategy.PROPERTY_KEY__FIELD_TYPE)]?.value |
| |
| if (!it.idOrUUID && !it.version && !it.dirtyMark) { |
| var functionTypingAPI = new FunctionTypingAPI() |
| val functionImagePicker = functionTypingAPI.functionImagePickerTypeName |
| if (it.isDomainKey || it.isDomainDescription || |
| (!fieldType.nullOrEmpty && fieldType.equals(ILayoutingStrategy.PROPERTY_SUGGESTTEXT))) { |
| suspect = type.createSuggestTextField(it, opInfoMap) |
| } else if (properties.exists[key.toLowerCase.equals(ILayoutingStrategy.PROPERTY_BLOB)]) { |
| suspect = type.createBlopUploadComponent(it) |
| } else if (!fieldType.nullOrEmpty && fieldType.equals(ILayoutingStrategy.PROPERTY_RICH_TEXT)) { |
| suspect = type.createRichTextField(it) |
| } else if (!fieldType.nullOrEmpty && fieldType.equals(ILayoutingStrategy.PROPERTY_MASKED_TEXT)) { |
| val mask = properties.findFirst[it.key.equals(ILayoutingStrategy.PROPERTY_MASK)]?.value |
| suspect = type.createMaskedTextField(it, mask) |
| } else if (!fieldType.nullOrEmpty && fieldType.equals(ILayoutingStrategy.PROPERTY_PASSWORD)) { |
| suspect = type.createPasswordField(it) |
| } else if (properties.exists[key.equalsIgnoreCase(ILayoutingStrategy.PROPERTY_TEXTAREA)]) { |
| suspect = type.createTextAreaField(it) |
| } else if (properties.exists[key.equalsIgnoreCase(ILayoutingStrategy.PROPERTY_ORGANIZATION)]) { |
| suspect = type.createOrganizationComboBox(it) |
| } else if (properties.exists[key.equalsIgnoreCase(ILayoutingStrategy.PROPERTY_PERSPECTIVE)]) { |
| suspect = type.createPerspectiveComboBox(it) |
| } else if (properties.exists[key.equalsIgnoreCase(ILayoutingStrategy.PROPERTY_PRINTSERVICE)]) { |
| suspect = type.createPrintServiceComboBox(it) |
| } else if (properties.exists[key.equalsIgnoreCase(ILayoutingStrategy.PROPERTY_THEME)]) { |
| suspect = type.createThemeComboBox(it) |
| } else if (properties.exists[key.equalsIgnoreCase(functionImagePicker)]) { |
| suspect = type.createIconComboBox(it) |
| } else { |
| suspect = type.createTextField(it) |
| } |
| } |
| } else if (type.date) { |
| suspect = type.createDateField(it) |
| } else if (type.enum) { |
| if (properties.exists[key.toLowerCase.equals(ILayoutingStrategy.PROPERTY_OPTION_GROUP)]) { |
| suspect = type.createEnumOptionsGroup(it) |
| } else { |
| suspect = type.createEnumComboBox(it) |
| } |
| } else if (type.byteArray) { |
| val fieldType = properties.findFirst[it.key.equals(ILayoutingStrategy.PROPERTY_KEY__FIELD_TYPE)]?.value |
| if (!fieldType.nullOrEmpty && fieldType.equals(ILayoutingStrategy.PROPERTY_RICH_TEXT)) { |
| suspect = type.createRichTextField(it) |
| } else { |
| suspect = type.createBlopUploadComponent(it) |
| } |
| } else if (it.domainReference) { |
| suspect = type.createBeanReferenceField(it) |
| } else if (it.field !== null && it.field.collection) { |
| if (properties.exists[key.toLowerCase.equals(ILayoutingStrategy.PROPERTY_GRID)]) { |
| suspect = type.createGrid(it) |
| } else if (properties.exists[key.equalsIgnoreCase(ILayoutingStrategy.PROPERTY_TABLE)]) { |
| suspect = type.createTableField(it) |
| } |
| } else if (type.dto) { |
| suspect = type.createDtoSuspect(it) |
| } |
| if (parentSuspect === null) { |
| type.completeSuspect(it, suspect, dtoType) |
| } else { |
| type.completeSuspect(it, suspect, parentSuspect, dtoType) |
| } |
| for (keyAndValue : properties) { |
| if(suspect !== null) suspect.properties.put(keyAndValue.key.toLowerCase, keyAndValue.value) |
| } |
| ] |
| } |
| |
| def createAuthorizationVisibilityProcessor(YAuthorizationable element, OperationInfo info) { |
| if (info.field !== null) { |
| val type = info.field.eContainer as JvmGenericType |
| if (!info.getter.returnType.type.isClass && info.getter.returnType.type.isAllowed(type, info)) { |
| element.authorizationGroup = type.fullyQualifiedName.toString |
| element.authorizationId = info.field.simpleName |
| } |
| } |
| } |
| |
| def YSuspect createDtoSuspect(JvmType type, OperationInfo info) { |
| val dtoSuspect = YECviewFactory.eINSTANCE.createYTypedCompoundSuspect |
| dtoSuspect.tags += ILayoutingStrategy.TAG__DTO |
| if (type instanceof JvmDeclaredType) { |
| type.createSuspectStructure(false, dtoSuspect) |
| } |
| |
| return dtoSuspect |
| } |
| |
| /** |
| * A suspect that is created for each sub type of beanType.<br> |
| * 1) we create a compound suspect<br> |
| * 2) we add the compound suspect to the layout<br> |
| * 3) we create a typed suspect for each operation info<br> |
| * 4) we add the new typed suspect to the compound suspect and create a tree<br> |
| */ |
| def YSuspect createSubTypeDtoSuspect(JvmDeclaredType subDtoJvmType) { |
| val subTypeSuspect = YECviewFactory.eINSTANCE.createYSubTypeSuspect |
| subTypeSuspect.tags += ILayoutingStrategy.TAG__SUBTYPE |
| subTypeSuspect.typeQualifiedName = subDtoJvmType.qualifiedName |
| subTypeSuspect.type = computer.loadClass(uiLayout.eResource.resourceSet, subTypeSuspect.typeQualifiedName) |
| |
| // create a new beanslot with the subtype. The main slot will become bound to this slot |
| val YView view = computer.currentView |
| val YDetailBeanSlot detailSlot = view.addDetailBeanSlot(subTypeSuspect.typeQualifiedName, subTypeSuspect.type, |
| yMainBeanslot, ""); |
| detailSlot.tags += ILayoutingStrategy.TAG__SUBTYPE |
| |
| // assign the detail bean slot to the sub type suspect for bindings later |
| subTypeSuspect.beanSlot = detailSlot |
| |
| // add the new suspect to the layout |
| layouter.add(subTypeSuspect) |
| |
| // create a new child node in the suspect hierarchy |
| layouter.pushHierarchy(subTypeSuspect) |
| |
| // create a hierarchy for the sub dto suspects |
| // Gets the operation infos for the given type in form of a map and converts the |
| // operation info map into a sorted list |
| val subTypeInfos = createSortedMapList(OperationExtensions.getOperationInfos(subDtoJvmType, false)) |
| |
| subTypeInfos.createSuspectStructure(subDtoJvmType, mobile, subTypeSuspect) |
| |
| // pop the latest subDtoSuspect |
| layouter.popHierarchy |
| |
| return subTypeSuspect |
| } |
| |
| /** |
| * Returns true, if the type is a dto. |
| */ |
| def boolean isDto(JvmType type) { |
| val collector = new SuperTypeCollector() |
| val superTypes = collector.collectSuperTypeNames(type) |
| |
| // if any of the supertype names equals org.eclipse.osbp.dsl.common.datatypes.IDto |
| return superTypes.contains(typeof(IDto).name) |
| } |
| |
| def completeSuspect(JvmType type, OperationInfo info, YSuspect suspect, JvmType parentType) { |
| if (suspect !== null) { |
| suspect.id = '''«uiLayout.generateId».«info.name»''' |
| |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| |
| if(info.isOnKanbanCard) { |
| suspect.tags += "onKanbanCard" |
| } |
| |
| if (info.isUniqueEntry) { |
| suspect.tags += "unique" |
| var splittedId = info.id.split(":") |
| if (splittedId.length > 1) { |
| var fqClassName = splittedId.get(0) |
| suspect.properties.put("class", fqClassName) |
| } |
| suspect.properties.put("name", info.name) |
| |
| // register the container of the binding to the suspect. Otherwise we can not check for the uniqueness |
| suspect.createModelValueContainerBinding(info.name, type, "value") |
| } |
| |
| if (isValidationConstraint(info)) { |
| suspect.tags += "constraint" |
| var splittedId = info.id.split(":") |
| if (splittedId.length > 1) { |
| var fqClassName = splittedId.get(0) |
| suspect.properties.put("class", fqClassName) |
| } |
| suspect.properties.put("name", info.name) |
| } |
| |
| layouter.add(suspect) |
| if (info.field !== null && info.field.collection) { |
| suspect.createModelListBinding(info, type, "list"); |
| } else { |
| suspect.createModelValueBinding(info.name, type, "value", parentType); |
| } |
| |
| // fix the masterDetailBinding endpoint of the child suspects |
| if (suspect instanceof YTypedCompoundSuspect) { |
| val masterValueEP = suspect.valueBindingEndpoints.get(0) |
| if (!suspect.valueBindingEndpoints.isEmpty) { |
| for (child : suspect.children) { |
| child.id = suspect.id + child.id |
| if (!child.valueBindingEndpoints.isEmpty) { |
| val childValueEP = child.valueBindingEndpoints.get(0) |
| if (childValueEP instanceof YDetailValueBindingEndpoint) { |
| childValueEP.masterObservable = EcoreUtil.copy(masterValueEP) as YValueBindingEndpoint |
| } |
| } |
| } |
| } |
| |
| } |
| |
| // create the authorization infos |
| suspect.createAuthorizationVisibilityProcessor(info) |
| } |
| } |
| |
| def completeSuspect(JvmType type, OperationInfo info, YSuspect suspect, YTypedCompoundSuspect parentSuspect, JvmType parentType) { |
| if (suspect !== null) { |
| suspect.id = '''«parentSuspect.id».«info.name»''' |
| |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| |
| if (isValidationConstraint(info)) { |
| suspect.tags += "constraint" |
| var splittedId = info.id.split(":") |
| if (splittedId.length > 1) { |
| var fqClassName = splittedId.get(0) |
| suspect.properties.put("class", fqClassName) |
| } |
| suspect.properties.put("name", info.name) |
| } |
| |
| parentSuspect.children.add(suspect) |
| if (info.field !== null && info.field.collection) { |
| suspect.createModelListBinding(info, type, "list"); |
| } else { |
| suspect.createModelValueBinding(info.name, type, "value", parentType); |
| } |
| |
| // create the authorization infos |
| suspect.createAuthorizationVisibilityProcessor(info) |
| } |
| } |
| |
| /** |
| * Sorted the attributes with the primitive types first and the rest after. Also all collections were left out. |
| */ |
| def createSortedOpInfoMapForCollections(Map<String, OperationInfo> opInfoMap) { |
| val sortedOpInfoList = <String, OperationInfo>newLinkedHashMap() |
| val nonPrimitiveOpInfoMap = <String, OperationInfo>newLinkedHashMap() |
| opInfoMap.forEach [ key, opInfo | |
| var JvmType detailType |
| // do not create a column if field is a collection |
| if (opInfo.field !== null && !opInfo.field.collection) { |
| detailType = opInfo.getter.returnType.type |
| |
| val isPrimitive = detailType instanceof JvmPrimitiveType || detailType.getQualifiedName().equals( |
| typeof(String).getName()); |
| |
| if (isPrimitive) { |
| sortedOpInfoList.put(key, opInfo) |
| } else { |
| nonPrimitiveOpInfoMap.put(key, opInfo) |
| } |
| } |
| ] |
| sortedOpInfoList.putAll(nonPrimitiveOpInfoMap) |
| sortedOpInfoList |
| } |
| |
| /** |
| * Sorted the attributes in a individual but fix order. |
| */ |
| def createSortedMapList(Map<String, OperationInfo> opInfoMap) { |
| val sortedOpInfoList = <Map<String, OperationInfo>>newLinkedList() |
| |
| // At this moment the order of the following method is not desired. See #203. |
| // +++++ Due to the not existing sorting the following lines of code are replaced by ... |
| /* |
| * val domainKeyOpInfoMap = <String, OperationInfo>newHashMap() |
| * val constraintsOpInfoMap = <String, OperationInfo>newHashMap() |
| * val indexOpInfoMap = <String, OperationInfo>newHashMap() |
| * val stringOpInfoMap = <String, OperationInfo>newHashMap() |
| * val restOpInfoMap = <String, OperationInfo>newHashMap() |
| |
| * // extract String-OperationInfos into a new Map to display later and display all string attributes first. |
| * opInfoMap.forEach [ key, opInfo | |
| * val type = opInfo.getter.returnType.type |
| * if (opInfo !== null && isDomainKey(opInfo)) { |
| * domainKeyOpInfoMap.put(key, opInfo) |
| * } else if (opInfo !== null && isIndex(opInfo)) { |
| * indexOpInfoMap.put(key, opInfo) |
| * } else if (type.string) { |
| * stringOpInfoMap.put(key, opInfo) |
| * } else { |
| * restOpInfoMap.put(key, opInfo) |
| * } |
| * ] |
| * sortedOpInfoList.add(domainKeyOpInfoMap) |
| * sortedOpInfoList.add(indexOpInfoMap) |
| * sortedOpInfoList.add(stringOpInfoMap) |
| * sortedOpInfoList.add(constraintsOpInfoMap) |
| * sortedOpInfoList.add(restOpInfoMap) |
| */ |
| // ++++ ... this line. |
| sortedOpInfoList.add(opInfoMap) |
| sortedOpInfoList |
| } |
| |
| def isDomainKey(OperationInfo info) { |
| if (info !== null && info.field !== null) { |
| for (annotationRefs : info.field.annotations) { |
| if (DomainKey.canonicalName.equals(annotationRefs.annotation.identifier)) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| def isOnKanbanCard(OperationInfo info) { |
| if (info !== null && info.field !== null) { |
| for (annotationRefs : info.field.annotations) { |
| if (OnKanbanCard.canonicalName.equals(annotationRefs.annotation.identifier)) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| def isDomainDescription(OperationInfo info) { |
| if (info !== null && info.field !== null) { |
| for (annotationRefs : info.field.annotations) { |
| if (DomainDescription.canonicalName.equals(annotationRefs.annotation.identifier)) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| def isValidationConstraint(OperationInfo info) { |
| if (info !== null && info.field !== null) { |
| for (annotationRefs : info.field.annotations) { |
| if (annotationRefs.annotation.identifier !== null && |
| annotationRefs.annotation.identifier.equals(Valid.canonicalName)) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| def isUniqueEntry(OperationInfo info) { |
| if (info !== null && info.field !== null) { |
| for (annotationRefs : info.field.annotations) { |
| if (annotationRefs.annotation.identifier !== null && |
| annotationRefs.annotation.identifier.equals(UniqueEntry.canonicalName)) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| def isIndex(OperationInfo info) { |
| if (info !== null && info.field !== null) { |
| for (annotationRefs : info.field.annotations) { |
| if (DomainKey.canonicalName.equals(annotationRefs.annotation.identifier)) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| /** |
| * Returns true, if the type is boolean |
| * |
| * @param type |
| * @return |
| */ |
| def isByteArray(JvmType type) { |
| if (type === null) |
| return false; |
| if (isArray(type, Byte) || isArray(type, Byte.TYPE)) { |
| return true; |
| } |
| return false; |
| } |
| |
| def isArray(JvmType type, Class<?> clazz) { |
| if (type === null) |
| return false; |
| var className = clazz.getName(); |
| if (className.charAt(0) == '[') { |
| className = clazz.getCanonicalName(); |
| } |
| className = className.concat("[]") |
| var result = className.equals(type.getIdentifier()); |
| return result; |
| } |
| |
| def YTypedSuspect createTextField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__TEXT |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YTypedSuspect createSuggestTextField(JvmType type, OperationInfo info, Map<String, OperationInfo> opInfoMap) { |
| val OperationInfo idAttInfo = opInfoMap.values.toIdInfo |
| if (idAttInfo === null) { |
| return createTextField(type, info) |
| } |
| |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__SUGGEST_TEXT |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, beanType.qualifiedName) |
| suspect.typeQualifiedName = beanType.qualifiedName |
| |
| suspect.properties.put(ILayoutingStrategy.PROPERTY__ITEM_CAPTION, info.name) |
| suspect.properties.put(ILayoutingStrategy.PROPERTY__ITEM_FILTER, info.name) |
| suspect.properties.put(ILayoutingStrategy.PROPERTY__ITEM_UUID, idAttInfo.name) |
| |
| suspect |
| } |
| |
| /** |
| * Returns the operation info for the id property. |
| */ |
| def OperationInfo getToIdInfo(Collection<OperationInfo> infos) { |
| |
| for (OperationInfo info : infos) { |
| if (info.idOrUUID) { |
| return info |
| } |
| } |
| return null |
| } |
| |
| def YTypedSuspect createTextAreaField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__TEXTAREA |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YTypedSuspect createDecimalField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__DECIMAL |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YTypedSuspect createNumberField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__NUMBER |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YTypedSuspect createCheckbox(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__BOOLEAN |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YTypedSuspect createDateField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__DATE |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YTypedSuspect createIconComboBox(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__IMAGE_PICKER |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YTypedSuspect createEnumComboBox(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__ENUM_COMBO |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| suspect |
| } |
| |
| def YTypedSuspect createOrganizationComboBox(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__ORGANIZATION_COMBO |
| suspect.type = typeof(String) |
| suspect.typeQualifiedName = typeof(String).name |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| suspect |
| } |
| |
| def YTypedSuspect createPerspectiveComboBox(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__PERSPECTIVE_COMBO |
| suspect.type = typeof(String) |
| suspect.typeQualifiedName = typeof(String).name |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| suspect |
| } |
| |
| def YTypedSuspect createThemeComboBox(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__THEME_COMBO |
| suspect.type = typeof(String) |
| suspect.typeQualifiedName = typeof(String).name |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| suspect |
| } |
| |
| def YTypedSuspect createPrintServiceComboBox(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__PRINTSERVICE_COMBO |
| suspect.type = typeof(String) |
| suspect.typeQualifiedName = typeof(String).name |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| suspect |
| } |
| |
| def YTypedSuspect createEnumOptionsGroup(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__ENUM_OPTIONS |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect.id = '''«uiLayout.generateId».«info.name»''' |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| suspect |
| } |
| |
| def YTypedSuspect createBeanReferenceField(JvmType type, OperationInfo info) { |
| var YTypedSuspect suspect = null |
| var suspectType = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| var captionProperty = BeanHelper.findCaptionProperty(suspectType) |
| var captionDescription = BeanHelper.findDescriptionProperty(suspectType) |
| if (captionProperty !== null || captionDescription !== null) { |
| suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.type = suspectType |
| suspect.tags += ILayoutingStrategy.TAG__BEAN_REFERENCE |
| suspect.id = '''«uiLayout.generateId».«info.name»''' |
| |
| if (info.readonly) { |
| suspect.tags += "readonly" |
| } |
| |
| if (info.hasAnnotation(FilterDepth)) { |
| val depth = toFilterDepth(info.field) |
| suspect.properties.put(ILayoutingStrategy.PROPERTY__FILTER_DEPTH, Integer.toString(depth)) |
| } |
| |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect.properties.put(ILayoutingStrategy.PROPERTY__ITEM_CAPTION, captionProperty) |
| suspect.properties.put(ILayoutingStrategy.PROPERTY__ITEM_DESCRIPTION, captionDescription) |
| } |
| |
| suspect |
| } |
| |
| def YTypedSuspect createTableField(JvmType type, OperationInfo info) { |
| type.createCollection(info, ILayoutingStrategy.TAG__TABLE) |
| } |
| |
| def YTypedSuspect createGrid(JvmType type, OperationInfo info) { |
| type.createCollection(info, ILayoutingStrategy.TAG__GRID) |
| } |
| |
| def YTypedSuspect createCollection(JvmType type, OperationInfo info, String tag) { |
| val suspect = YECviewFactory.eINSTANCE.createYCollectionSuspect |
| val JvmParameterizedTypeReference collectionType = info.getter.returnType as JvmParameterizedTypeReference |
| val JvmTypeReference typeInCollection = collectionType.arguments.get(0) |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, typeInCollection.type.qualifiedName) |
| suspect.tags += tag |
| suspect.typeQualifiedName = typeInCollection.type.qualifiedName |
| |
| // Not used! Has to be removed! |
| // var typeRef = info.field.type |
| // var JvmDeclaredType argType |
| if (typeInCollection.type instanceof JvmDeclaredType) { |
| val castedType = typeInCollection.type as JvmDeclaredType |
| |
| // TODO get props from JVMType |
| val propMap = castedType.toFieldProperties |
| val opInfoMap = OperationExtensions.getOperationInfos(castedType) |
| val sortedOpInfoMap = createSortedOpInfoMapForCollections(opInfoMap) |
| sortedOpInfoMap.values.forEach [ |
| var JvmType detailType = it.getter.returnType.type |
| var YColumnInfo columnInfo = null |
| val isPrimitive = detailType instanceof JvmPrimitiveType; |
| if (it.isDomainReference) { |
| |
| // else use the domain key field and reserve them till the end |
| for (nestedInfo : JvmTypeProperties.getOperationInfos(detailType as JvmDeclaredType).values) { |
| if (nestedInfo.hasAnnotation(typeof(DomainKey))) { |
| val nestPropMap = (detailType as JvmDeclaredType).toFieldProperties |
| columnInfo = nestedInfo.type.createYColumnInfo |
| columnInfo.name = it.field.simpleName + "." + nestedInfo.attributePath |
| var propList = nestPropMap.get(nestedInfo.name) |
| columnInfo.setYColumnInfoProperties(propList) |
| } |
| } |
| } else if (!it.idOrUUID && !it.version && !it.dirtyMark) { |
| var JvmType objectType = it.field.type.type; |
| if (isPrimitive) { |
| val primitiveTypeName = it.field.type.type.qualifiedName |
| val InternalEObject proxy = TypesFactory.eINSTANCE.createJvmVoid as InternalEObject |
| proxy.eSetProxyURI(URI.createURI(toObjectProxy(primitiveTypeName))) |
| objectType = EcoreUtil.resolve(proxy, uiLayout.eResource) as JvmType |
| } |
| columnInfo = objectType.createYColumnInfo |
| columnInfo.name = it.name |
| var propList = propMap.get(it.field.identifier) |
| columnInfo.setYColumnInfoProperties(propList) |
| } |
| if (columnInfo !== null) { |
| |
| // TODO (JCD): Simple name instead of FQN till solution of ticket - #581 |
| columnInfo.labelI18nKey = columnInfo.name |
| suspect.columns += columnInfo |
| } |
| ] |
| } |
| suspect |
| } |
| |
| /** |
| * Creates a proxy object |
| **/ |
| def toObjectProxy(String primitiveTypeName) { |
| switch (primitiveTypeName) { |
| case "int": |
| return '''java:/Objects/java.lang.Integer#java.lang.Integer''' |
| default: |
| return '''java:/Objects/java.lang.«primitiveTypeName.toFirstUpper»#java.lang.«primitiveTypeName. |
| toFirstUpper»''' |
| } |
| } |
| |
| def void createMobileSwitch(JvmType type, OperationInfo info) { |
| val yField = vFactory.createVMSwitch |
| yField.initialEnabled = !info.readonly |
| |
| // yField.labelI18nKey = i18nRootKey + "." + info.name |
| yField.label = info.name |
| |
| layouter.add(yField) |
| |
| yField.createBinding(info, type, "value"); |
| } |
| |
| def YSuspect createRichTextField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| |
| if (type.string) { |
| suspect.tags += ILayoutingStrategy.TAG__RICH_TEXT__STRING |
| } else if (type.byteArray) { |
| suspect.tags += ILayoutingStrategy.TAG__RICH_TEXT__BLOB |
| } else { |
| throw new IllegalArgumentException( |
| "RichTextFields need to be bound to String or byte[]. " + type.qualifiedName + |
| " is not a valid option.") |
| } |
| |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YSuspect createMaskedTextField(JvmType type, OperationInfo info, String mask) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__MASKED_TEXT_FIELD |
| suspect.properties.put(ILayoutingStrategy.PROPERTY_MASK, mask) |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YSuspect createMaskedDecimalField(JvmType type, OperationInfo info, String mask) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__MASKED_DECIMAL_FIELD |
| suspect.properties.put(ILayoutingStrategy.PROPERTY_MASK, mask) |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YSuspect createPasswordField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| |
| if (type.string) { |
| suspect.tags += ILayoutingStrategy.TAG__PASSWORD |
| } else { |
| throw new IllegalArgumentException( |
| "PasswordField need to be bound to String. " + type.qualifiedName + " is not a valid option.") |
| } |
| |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YSuspect createBlopUploadComponent(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__BLOB |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| def YSuspect createCustomDecimalField(JvmType type, OperationInfo info) { |
| val suspect = YECviewFactory.eINSTANCE.createYTypedSuspect |
| suspect.tags += ILayoutingStrategy.TAG__DECIMAL |
| suspect.type = computer.loadClass(uiLayout.eResource.resourceSet, type.qualifiedName) |
| suspect.typeQualifiedName = type.qualifiedName |
| suspect |
| } |
| |
| /** |
| * Create the bindings and install at the view |
| */ |
| def createBinding(YEmbeddable yField, OperationInfo info, JvmType type, String fieldProperty) { |
| |
| // use the autoWireSource as the model endpoint |
| val UiBindingEndpointAssignment uiModelEndpoint = uiLayout.autoWireSource as UiBindingEndpointAssignment |
| val yModelEndpoint = computer.createValueBindingEndpoint(uiModelEndpoint) |
| val detailValueEndpoint = yModelEndpoint.createDetailValueEndpoint |
| detailValueEndpoint.propertyPath = info.name |
| detailValueEndpoint.type = computer.loadClass(uiLayout.eResource.resourceSet, beanType.qualifiedName) |
| |
| // create the field endpoint |
| val yFieldEndpoint = BindingFactory.eINSTANCE.createYECViewModelValueBindingEndpoint |
| yFieldEndpoint.element = yField |
| yFieldEndpoint.propertyPath = fieldProperty |
| yFieldEndpoint.typeQualifiedName = beanType.qualifiedName |
| yFieldEndpoint.type = computer.loadClass(uiLayout.eResource.resourceSet, beanType.qualifiedName) |
| if (yFieldEndpoint.type !== null && yFieldEndpoint.type.isAssignableFrom(typeof(EObject))) { |
| yFieldEndpoint.emfNsURI = yField.eClass.EPackage.nsURI |
| } |
| |
| // bind model to target |
| val yBinding = BindingFactory.eINSTANCE.createYValueBinding(); |
| yBinding.setTargetEndpoint(yFieldEndpoint); |
| yBinding.setModelEndpoint(detailValueEndpoint); |
| yBinding.setModelToTargetStrategy(YBindingUpdateStrategy.UPDATE); |
| yBinding.setTargetToModelStrategy( |
| if(info.readonly) YBindingUpdateStrategy.NEVER else YBindingUpdateStrategy.UPDATE) |
| |
| // register the binding at the current view |
| yLayout.view.orCreateBindingSet.bindings += yBinding |
| |
| // set the i18n key based on the binding |
| // yField.labelI18nKey = I18nKeyProvider.toI18nKey(beanType.qualifiedName, detailValueEndpoint.propertyPath) |
| yField.labelI18nKey = detailValueEndpoint.propertyPath |
| } |
| |
| /** |
| * Create the bindings and install at the view |
| */ |
| def createModelValueBinding(YSuspect suspect, String propertyPath, JvmType type, String fieldProperty, JvmType parentType) { |
| |
| val YBeanSlot subTypeBeanSlot = suspect.findSubTypeBeanSlot |
| var YValueBindingEndpoint endpoint = null |
| var path = "" |
| |
| // If a subTypeBeanSlot could be found, then we need to create a binding endpoint against this beanslot. |
| // The main slot has a different type then detail beanslot. And we can not bind fields contained in the subtype |
| // to the main bean slot. Eclipse databinding requires a proper type at binding creation. |
| if (subTypeBeanSlot === null) { |
| |
| // use the autoWireSource as the model endpoint |
| val UiBindingEndpointAssignment uiModelEndpoint = uiLayout. |
| autoWireSource as UiBindingEndpointAssignment |
| val yModelEndpoint = computer.createValueBindingEndpoint(uiModelEndpoint) |
| val detailValueEndpoint = yModelEndpoint.createDetailValueEndpoint |
| detailValueEndpoint.propertyPath = propertyPath |
| detailValueEndpoint.type = computer.loadClass(uiLayout.eResource.resourceSet, |
| parentType.qualifiedName) |
| endpoint = detailValueEndpoint |
| path = detailValueEndpoint.propertyPath |
| } else { |
| endpoint = subTypeBeanSlot.createBindingEndpoint(propertyPath) |
| path = propertyPath |
| } |
| |
| suspect.getValueBindingEndpoints().add(endpoint); |
| |
| // set the i18n key based on the binding |
| // suspect.labelI18nKey = I18nKeyProvider.toI18nKey(beanType.qualifiedName, path) |
| suspect.labelI18nKey = path |
| suspect.label = propertyPath |
| } |
| |
| /** |
| * Creates a binding which points to the container of the property |
| */ |
| def createModelValueContainerBinding(YSuspect suspect, String propertyPath, JvmType type, String property) { |
| |
| var fieldProperty = property |
| if (fieldProperty.contains(".")) { |
| fieldProperty = fieldProperty.substring(0, fieldProperty.lastIndexOf(".")) |
| } else { |
| fieldProperty = null |
| } |
| |
| val YBeanSlot subTypeBeanSlot = suspect.findSubTypeBeanSlot |
| var YValueBindingEndpoint endpoint = null |
| |
| // If a subTypeBeanSlot could be found, then we need to create a binding endpoint against this beanslot. |
| // The main slot has a different type then detail beanslot. And we can not bind fields contained in the subtype |
| // to the main bean slot. Eclipse databinding requires a proper type at binding creation. |
| if (subTypeBeanSlot === null) { |
| |
| // use the autoWireSource as the model endpoint |
| val UiBindingEndpointAssignment uiModelEndpoint = uiLayout. |
| autoWireSource as UiBindingEndpointAssignment |
| val yModelEndpoint = computer.createValueBindingEndpoint(uiModelEndpoint) |
| endpoint = yModelEndpoint |
| if (fieldProperty !== null) { |
| val detailValueEndpoint = yModelEndpoint.createDetailValueEndpoint |
| detailValueEndpoint.propertyPath = propertyPath |
| detailValueEndpoint.type = computer.loadClass(uiLayout.eResource.resourceSet, |
| beanType.qualifiedName) |
| endpoint = detailValueEndpoint |
| } |
| } else { |
| endpoint = subTypeBeanSlot.createBindingEndpoint(propertyPath) |
| } |
| |
| suspect.containerValueBindingEndpoint = endpoint |
| } |
| |
| /** |
| * Checks if the suspect is contained in an YSubTypeSuspect. <br> |
| * If so, then the detail beanslot of the YSubTypeSuspect is returned. Null otherwise. |
| */ |
| def YBeanSlot findSubTypeBeanSlot(YSuspect suspect) { |
| if (suspect === null) { |
| return null |
| } |
| if (suspect instanceof YSubTypeSuspect) { |
| return suspect.beanSlot |
| } |
| |
| val parent = suspect.eContainer |
| if (parent instanceof YSuspect) { |
| return parent.findSubTypeBeanSlot |
| } |
| return null |
| } |
| |
| /** |
| * Create the bindings and install at the view |
| */ |
| def createModelListBinding(YSuspect suspect, OperationInfo info, JvmType type, String fieldProperty) { |
| |
| val YBeanSlot subTypeBeanSlot = suspect.findSubTypeBeanSlot |
| var YListBindingEndpoint endpoint = null |
| if (subTypeBeanSlot === null) { |
| // use the autoWireSource as the model endpoint |
| val UiBindingEndpointAssignment uiModelEndpoint = uiLayout. |
| autoWireSource as UiBindingEndpointAssignment |
| endpoint = createListBindingEndpointWithNested(uiModelEndpoint, info.name) |
| } else { |
| endpoint = subTypeBeanSlot.createListBindingEndpoint(info.name, subTypeBeanSlot.valueType) |
| } |
| |
| suspect.getValueBindingEndpoints().add(endpoint); |
| |
| // set the i18n key based on the binding |
| // suspect.labelI18nKey = I18nKeyProvider.toI18nKey(beanType.qualifiedName, info.name) |
| suspect.labelI18nKey = info.name |
| suspect.label = info.name |
| } |
| |
| /** |
| * Creates a listbinding with respect to nested collection fields. <p> |
| * For instance:<br> |
| * beanSlot contains Person. We want to bind the children of persons father to a table. |
| * So we need to access the children collection of the beanslot by a nested property path: <code>beanslot.father.children</code> |
| */ |
| def YListBindingEndpoint createListBindingEndpointWithNested(UiBindingEndpointAssignment epDef, |
| String attributePath) { |
| if (epDef === null) { |
| return null |
| } |
| |
| var YListBindingEndpoint result = null; |
| val BindingInfoHelper.BindingInfo info = new BindingInfoHelper.BindingInfo() |
| bindingInfoHelper.collectBindingInfo(epDef, info); |
| |
| if (info.bindingRoot instanceof UiBeanSlot) { |
| val uiBeanSlot = info.bindingRoot as UiBeanSlot |
| |
| val YBeanSlot yBeanSlot = computer.associatedUi(uiBeanSlot) |
| val YBeanSlotListBindingEndpoint ep = factory.createBeanSlotListBindingEndpoint |
| ep.beanSlot = yBeanSlot |
| |
| ep.attributePath = toNestedCollectionPath(info, attributePath) |
| result = ep |
| } else if (info.bindingRoot instanceof UiEmbeddable) { |
| val YEmbeddable yElement = computer.associatedUi(info.bindingRoot) |
| val YECViewModelListBindingEndpoint ep = factory.createECViewModelListBindingEndpoint |
| ep.element = yElement |
| ep.propertyPath = toNestedCollectionPath(info, attributePath) |
| if (info.typeForBinding !== null) { |
| ep.typeQualifiedName = info.typeForBinding.qualifiedName |
| ep.type = computer.loadClass(epDef.eResource.resourceSet, ep.typeQualifiedName) |
| } |
| if (yElement !== null) { |
| ep.emfNsURI = yElement.eClass.EPackage.nsURI |
| } |
| result = ep |
| } |
| |
| return result |
| } |
| |
| def toNestedCollectionPath(BindingInfo info, String attributePath) { |
| val StringBuilder b = new StringBuilder |
| if (!info.path.toString.nullOrEmpty) { |
| b.append(info.path.toString) |
| } |
| |
| if (!attributePath.nullOrEmpty) { |
| if (b.length > 0) { |
| b.append(".") |
| } |
| b.append(attributePath) |
| } |
| val pathResult = b.toString |
| pathResult |
| } |
| |
| /** |
| * Creates y column info element |
| */ |
| def YColumnInfo createYColumnInfo(JvmType type) { |
| val YColumnInfo columnInfo = YECviewFactory.eINSTANCE.createYColumnInfo |
| |
| columnInfo.typeQualifiedName = type.qualifiedName |
| columnInfo.type = computer.loadClass(uiLayout.eResource.resourceSet, columnInfo.typeQualifiedName) |
| columnInfo |
| } |
| |
| /** |
| * Sets properties into y column info |
| */ |
| def setYColumnInfoProperties(YColumnInfo columnInfo, List<AutowireUtil.Pair> propList) { |
| var properties = columnInfo.properties |
| if (propList !== null) { |
| for (prop : propList) { |
| properties.put(prop.key, prop.value) |
| } |
| } |
| } |
| |
| public interface Layouter { |
| def void setup(UiLayout uiRootLayout, YLayout yRootLayout) |
| |
| def void add(YEmbeddable element); |
| |
| def void add(YSuspect suspect); |
| |
| def void pushHierarchy(YTypedCompoundSuspect suspect); |
| |
| def void popHierarchy(); |
| |
| } |
| |
| public static class MobileLayouter implements Layouter { |
| |
| VMVerticalComponentGroup group |
| |
| override setup(UiLayout uiRootLayout, YLayout yRootLayout) { |
| group = VaadinMobileFactory.eINSTANCE.createVMVerticalComponentGroup |
| |
| yRootLayout.elements += group |
| } |
| |
| override add(YEmbeddable element) { |
| group.addElement(element) |
| } |
| |
| override add(YSuspect ySuspect) { |
| // layout.suspects += ySuspect |
| } |
| |
| override pushHierarchy(YTypedCompoundSuspect suspect) { |
| throw new UnsupportedOperationException("TODO: auto-generated method stub") |
| } |
| |
| override popHierarchy() { |
| throw new UnsupportedOperationException("TODO: auto-generated method stub") |
| } |
| |
| } |
| |
| public static class StrategyLayoutLayouter implements Layouter { |
| |
| Stack<YTypedCompoundSuspect> currentSubDtoSuspect = new Stack |
| YStrategyLayout layout |
| |
| override setup(UiLayout uiRootLayout, YLayout yRootLayout) { |
| layout = YECviewFactory.eINSTANCE.createYStrategyLayout |
| layout.id = "cx-StrategyLayout" |
| |
| yRootLayout.elements += layout |
| yRootLayout.view.visibilityProcessors += |
| YVisibilityFactory.eINSTANCE.createYAuthorizationVisibilityProcessor |
| if (yRootLayout instanceof YAlignmentContainer) { |
| yRootLayout.applyAlignment(layout, YAlignment.FILL_FILL) |
| } |
| } |
| |
| override add(YEmbeddable element) { |
| } |
| |
| override add(YSuspect ySuspect) { |
| if (!currentSubDtoSuspect.isEmpty) { |
| currentSubDtoSuspect.peek.children += ySuspect |
| } else { |
| layout.suspects += ySuspect |
| } |
| } |
| |
| override pushHierarchy(YTypedCompoundSuspect suspect) { |
| currentSubDtoSuspect.push(suspect) |
| } |
| |
| override popHierarchy() { |
| currentSubDtoSuspect.pop |
| } |
| |
| } |
| |
| /** |
| * The Class LocalResourceAccess. |
| */ |
| public static class LocalResourceAccess implements IReferenceFinder.ILocalResourceAccess { |
| |
| ResourceSet rs |
| |
| new(ResourceSet rs) { |
| this.rs = rs |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.xtext.findReferences.IReferenceFinder.IResourceAccess |
| * #readOnly(org.eclipse.emf.common.util.URI, |
| * org.eclipse.xtext.util.concurrent.IUnitOfWork) |
| */ |
| override <R> R readOnly(URI targetURI, IUnitOfWork<R, ResourceSet> work) { |
| return work.exec(rs); |
| } |
| } |
| } |
| |