| /** |
| * Copyright (c) 2011, 2014 - Lunifera GmbH (Gross Enzersdorf, Austria), 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.dsl.dto.xtext.extensions |
| |
| import com.google.inject.Inject |
| import java.util.Collections |
| import java.util.List |
| import org.eclipse.osbp.dsl.common.xtext.extensions.TreeAppendableExtensions |
| import org.eclipse.osbp.dsl.common.xtext.jvmmodel.CommonTypesBuilder |
| import org.eclipse.osbp.dsl.dto.lib.ICrossReference |
| import org.eclipse.osbp.dsl.dto.lib.IMapper |
| import org.eclipse.osbp.dsl.dto.lib.IMapperAccess |
| import org.eclipse.osbp.dsl.dto.lib.MappingContext |
| import org.eclipse.osbp.dsl.dto.xtext.jvmmodel.AnnotationCompiler |
| import org.eclipse.osbp.dsl.entity.xtext.extensions.Constants |
| import org.eclipse.osbp.dsl.semantic.common.types.LAttribute |
| import org.eclipse.osbp.dsl.semantic.common.types.LClass |
| import org.eclipse.osbp.dsl.semantic.common.types.LFeature |
| import org.eclipse.osbp.dsl.semantic.common.types.LPackage |
| import org.eclipse.osbp.dsl.semantic.common.types.LReference |
| import org.eclipse.osbp.dsl.semantic.common.types.LType |
| import org.eclipse.osbp.dsl.semantic.dto.LDto |
| import org.eclipse.osbp.dsl.semantic.dto.LDtoAbstractAttribute |
| import org.eclipse.osbp.dsl.semantic.dto.LDtoAbstractReference |
| import org.eclipse.osbp.dsl.semantic.dto.LDtoFeature |
| import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedAttribute |
| import org.eclipse.osbp.dsl.semantic.entity.LBean |
| import org.eclipse.osbp.dsl.semantic.entity.LEntity |
| import org.eclipse.osbp.dsl.semantic.entity.LEntityFeature |
| import org.eclipse.osbp.dsl.semantic.entity.LOperation |
| import org.eclipse.osbp.runtime.common.annotations.DomainDescription |
| import org.eclipse.xtext.common.types.JvmField |
| import org.eclipse.xtext.common.types.JvmGenericType |
| import org.eclipse.xtext.common.types.JvmOperation |
| import org.eclipse.xtext.common.types.JvmParameterizedTypeReference |
| import org.eclipse.xtext.common.types.JvmTypeReference |
| import org.eclipse.xtext.common.types.JvmVisibility |
| import org.eclipse.xtext.common.types.TypesFactory |
| import org.eclipse.xtext.common.types.util.TypeReferences |
| import org.eclipse.xtext.naming.IQualifiedNameProvider |
| import org.eclipse.xtext.naming.QualifiedName |
| import org.eclipse.xtext.xbase.XExpression |
| import org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociations |
| import org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociator |
| import org.eclipse.xtext.xbase.lib.Procedures.Procedure1 |
| |
| class DtoTypesBuilder extends CommonTypesBuilder { |
| |
| @Inject extension DtoModelExtensions |
| @Inject extension MethodNamingExtensions |
| @Inject extension TreeAppendableExtensions |
| @Inject extension IQualifiedNameProvider |
| @Inject extension AnnotationExtension |
| |
| @Inject |
| private IJvmModelAssociator associator; |
| @Inject AnnotationCompiler annotationCompiler |
| @Inject TypesFactory typesFactory; |
| @Inject TypeReferences references; |
| |
| def htmlCode(CharSequence s) { |
| "<code>".concat(String::valueOf(s)).concat("</code>") |
| } |
| |
| def JvmField toDiposeField(LDto sourceElement) { |
| val JvmField field = sourceElement.toPrimitiveTypeField("disposed", Boolean::TYPE) |
| associate(sourceElement, field) |
| annotationCompiler.addDisposeFieldAnnotation(sourceElement, field) |
| return field |
| } |
| |
| def JvmOperation toDispose(LDto lClass) { |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, lClass) |
| op.simpleName = "dispose" |
| op.documentation = ''' |
| Calling dispose will destroy that instance. The internal state will be |
| set to 'disposed' and methods of that object must not be used anymore. |
| Each call will result in runtime exceptions.<br/> |
| If this object keeps composition containments, these will be disposed too. |
| So the whole composition containment tree will be disposed on calling this method.''' |
| |
| annotationCompiler.addDisposeFieldAnnotation(lClass, op) |
| |
| setBody(op, |
| [ // ITreeAppendable |
| if(it == null) return |
| val p = it.trace(lClass) |
| p >> ''' |
| if (isDisposed()) { |
| return; |
| } |
| ''' |
| val compositionContainmentProps = lClass.features.filter[cascading] |
| if (!compositionContainmentProps.empty) { |
| p >> "try " >>> "{" |
| p >> "// Dispose all the composition references.\n" |
| for (prop : compositionContainmentProps) { |
| val fieldRef = "this.".concat(prop.toName.toFirstLower) |
| val typeName = prop.toTypeName |
| val typeVar = typeName.toFirstLower |
| if (prop.toMany) { |
| p >> ''' |
| if («fieldRef» != null) { |
| for («typeName» «typeVar» : «fieldRef») { |
| «typeVar».dispose(); |
| } |
| «fieldRef» = null; |
| } |
| ''' |
| } else { |
| p >> ''' |
| if («fieldRef» != null) { |
| «fieldRef».dispose(); |
| «fieldRef» = null; |
| } |
| ''' |
| } |
| } |
| p <<< "}" |
| p >>> "finally {" |
| |
| //p.increaseIndentation |
| } |
| if (lClass.superType != null) { |
| p >> "super.dispose();" |
| } else { |
| p >> "firePropertyChange(\"disposed\", this.disposed, this.disposed = true);" |
| } |
| if (!compositionContainmentProps.empty) { |
| p <<< "}" |
| } |
| ]) |
| |
| associate(lClass, op) |
| } |
| |
| def JvmOperation toMethod(LOperation sourceElement, String name, JvmTypeReference returnType, |
| Procedure1<? super JvmOperation> initializer) { |
| val op = typesFactory.createJvmOperation() |
| op.simpleName = name |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = cloneWithProxies(returnType) |
| |
| annotationCompiler.processAnnotation(sourceElement, op); |
| associate(sourceElement, op); |
| initializeSafely(op, initializer); |
| } |
| |
| def dispatch JvmOperation toSetter(LDtoAbstractAttribute prop) { |
| val paramName = prop.toMethodParamName |
| val typeRef = prop.toDtoTypeReferenceWithMultiplicity |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toSetterName |
| op.parameters += prop.toParameter(paramName, typeRef) |
| op.documentation = ''' |
| Sets the <code>«paramName»</code> property to this instance. |
| |
| @param «paramName» - the property |
| @throws RuntimeException if instance is <code>disposed</code> |
| ''' |
| |
| if (!prop.toMany) { |
| if(prop.toRawType.isBean) { |
| setBody(op, ''' |
| // ensure that embedded beans will notify their parent about changes |
| // so their dirty state can be handled properly |
| if (this.«paramName» != null) { |
| this.«paramName».removePropertyChangeListener(this); |
| } |
| |
| firePropertyChange("«paramName»", this.«paramName», this.«paramName» = «paramName» ); |
| |
| if (this.«paramName» != null) { |
| this.«paramName».addPropertyChangeListener(this); |
| } |
| ''') |
| }else{ |
| setBody(op, '''firePropertyChange("«paramName»", this.«paramName», this.«paramName» = «paramName» ); |
| «IF prop.IDorUUID» |
| installLazyCollections(); |
| «ENDIF» |
| ''') |
| } |
| |
| } else { |
| setBody(op, |
| [ // ITreeAppendable |
| if(it == null) return |
| val p = it.trace(prop); |
| p >> prop.toCheckDisposedCall() |
| val fieldRef = "this." + prop.toName |
| |
| p >> "for (" +prop.toDtoTypeReference.simpleName + " dto : " + prop.toCollectionInternalGetterName + "().toArray(new " + prop.toDtoTypeReference.simpleName + "[" + fieldRef + ".size()])) " >>> "{" |
| |
| p >> prop.toCollectionRemoverName + "(dto);" |
| p <<< "}" |
| |
| p >> "if(" + paramName +" == null)" >>> "{" |
| p >> "return;" |
| p <<< "}" |
| |
| p >> "for (" +prop.toDtoTypeReference.simpleName + " dto : " + paramName + ") " >>> "{" |
| p >> prop.toCollectionAdderName + "(dto);" |
| p <<< "}" |
| ]) |
| } |
| |
| return associate(prop, op); |
| } |
| |
| override String toSetDirtyStatement(LClass sourceElement) { |
| '''firePropertyChange("dirty", this.dirty, this.dirty = dirty );''' |
| } |
| |
| def JvmOperation toVersionSetter(LDtoAbstractAttribute prop) { |
| val paramName = prop.toMethodParamName |
| val typeRef = prop.toDtoTypeReferenceWithMultiplicity |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toSetterName |
| op.parameters += prop.toParameter(paramName, typeRef) |
| op.documentation = ''' |
| Sets the <code>«paramName»</code> property to this instance. |
| |
| @param «paramName» - the property |
| @throws RuntimeException if instance is <code>disposed</code> |
| ''' |
| setBody(op, ''' |
| firePropertyChange("«paramName»", this.«paramName», this.«paramName» = «paramName» ); |
| ''') |
| |
| |
| return associate(prop, op); |
| } |
| |
| def dispatch JvmOperation toSetter(LDtoAbstractReference prop) { |
| // if (prop.toMany) { |
| // throw new RuntimeException("toMany-References not allowed for setters!"); |
| // } |
| val paramName = prop.toMethodParamName |
| val typeRef = prop.toDtoTypeReferenceWithMultiplicity |
| val opposite = prop.opposite |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toSetterName |
| op.parameters += prop.toParameter(paramName, typeRef) |
| op.documentation = ''' |
| Sets the <code>«paramName»</code> property to this instance. |
| «IF (opposite != null)» |
| Since the reference has an opposite reference, the opposite <code>«prop.toTypeName»# |
| «opposite.name.toFirstLower»</code> of the <code>«paramName»</code> will be handled automatically and no |
| further coding is required to keep them in sync.<p> |
| See {@link «prop.toTypeName»#«opposite.toSetterName»(«prop.toTypeName») |
| «ENDIF» |
| |
| @param «paramName» - the property |
| @throws RuntimeException if instance is <code>disposed</code> |
| ''' |
| |
| op.body = ''' |
| checkDisposed(); |
| «IF opposite == null» |
| «IF !prop.toMany» |
| firePropertyChange("«paramName»", this.«paramName», this.«paramName» = «paramName»); |
| «ELSE» |
| for («prop.toDtoTypeReference.simpleName» dto : «prop.toCollectionInternalGetterName»().toArray(new «prop.toDtoTypeReference.simpleName»[this.«prop.toName».size()])) { |
| «prop.toCollectionRemoverName»(dto); |
| } |
| |
| if(«paramName» == null) { |
| return; |
| } |
| |
| for («prop.toDtoTypeReference.simpleName» dto : «paramName») { |
| «prop.toCollectionAdderName»(dto); |
| } |
| «ENDIF» |
| «ELSE» |
| «IF !prop.toMany» |
| if (this.«prop.toName» != null) { |
| «IF opposite.toMany» |
| this.«prop.toName».«opposite.toCollectionInternalRemoverName»(this); |
| «ELSE» |
| this.«prop.toName».«opposite.toInternalSetterName»(null); |
| «ENDIF» |
| } |
| |
| «prop.toInternalSetterName»(«paramName»); |
| |
| if (this.«prop.toName» != null) { |
| «IF opposite.toMany» |
| this.«prop.toName».«opposite.toCollectionInternalAdderName»(this); |
| «ELSE» |
| this.«prop.toName».«opposite.toInternalSetterName»(this); |
| «ENDIF» |
| } |
| «ELSE» |
| for («prop.toDtoTypeReference.simpleName» dto : «prop.toCollectionInternalGetterName»().toArray(new «prop.toDtoTypeReference.simpleName»[this.«prop.toName».size()])) { |
| «prop.toCollectionRemoverName»(dto); |
| } |
| |
| if(«paramName» == null) { |
| return; |
| } |
| |
| for («prop.toDtoTypeReference.simpleName» dto : «paramName») { |
| «prop.toCollectionAdderName»(dto); |
| } |
| «ENDIF» |
| «ENDIF» |
| ''' |
| return associate(prop, op); |
| } |
| |
| // dispatch used by sub classes |
| def dispatch JvmOperation toGetter(LDtoAbstractAttribute prop, String methodName) { |
| val propertyName = prop.toName |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.simpleName = methodName |
| op.returnType = cloneWithProxies(prop.toDtoTypeReferenceWithMultiplicity) |
| |
| if (prop.derived) { |
| val customDoc = prop.documentation |
| if (customDoc != null) { |
| op.documentation = customDoc |
| } else { |
| op.documentation = ''' |
| Calculates the value for the derived property «prop.name» |
| |
| @return «prop.name» The derived property value''' |
| } |
| |
| // set the domain description annotation |
| if (prop.domainDescription) { |
| op.annotations += prop.toAnnotation(typeof(DomainDescription)) |
| } |
| |
| setBody(op, prop.derivedGetterExpression) |
| |
| } else { |
| op.documentation = if (prop.toMany) { |
| "Returns an unmodifiable list of " + propertyName + "." |
| } else if (propertyName != null) { |
| "Returns the ".concat((if(prop.bounds.required) "<em>required</em> " else "")).concat(propertyName). |
| concat(" property").concat( |
| (if(!prop.toRawType.isBean && !prop.bounds.required) " or <code>null</code> if not present" else "")).concat(".") |
| } |
| |
| setBody(op, |
| [ // ITreeAppendable it | |
| if(it == null) return |
| val p = it.trace(prop); |
| if (prop.toMany) { |
| p >> "return " >> newTypeRef(prop, typeof(Collections)) >> ".unmodifiableList" >> |
| "(" + prop.toCollectionInternalGetterName + "());" |
| } else { |
| if(prop.toRawType.isBean) { |
| p >> "if(this." + propertyName + "== null)" >>> "{" |
| p >> "this." + propertyName + " = new " + prop.toRawType.toDTOBeanSimpleName + "();" |
| p <<< "}" |
| } |
| p >> "return this." + propertyName + ";" |
| } |
| ]) |
| } |
| return associate(prop, op); |
| } |
| |
| // dispatch used by sub classes |
| def dispatch JvmOperation toGetter(LDtoAbstractReference prop, String methodName) { |
| val propertyName = prop.toName |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.simpleName = methodName |
| op.returnType = cloneWithProxies(prop.toDtoTypeReferenceWithMultiplicity) |
| op.documentation = if (prop.toMany) { |
| "Returns an unmodifiable list of " + propertyName + "." |
| } else if (propertyName != null) { |
| "Returns the ".concat((if(prop.bounds.required) "<em>required</em> " else "")).concat(propertyName). |
| concat(" property").concat( |
| (if(!prop.toRawType.isBean && !prop.bounds.required) " or <code>null</code> if not present" else "")).concat(".") |
| } |
| |
| setBody(op, |
| [ // ITreeAppendable it | |
| if(it == null) return |
| val p = it.trace(prop); |
| if (prop.toMany) { |
| p >> "return " >> newTypeRef(prop, typeof(Collections)) >> ".unmodifiableList" >> |
| "(" + prop.toCollectionInternalGetterName + "());" |
| } else { |
| if(prop.toRawType.isBean) { |
| p >> "if(this." + propertyName + "== null)" >>> "{" |
| p >> "this." + propertyName + " = new " + prop.toRawType.toDTOBeanSimpleName + "();" |
| p <<< "}" |
| } |
| p >> "return this." + propertyName + ";" |
| } |
| ]) |
| |
| return associate(prop, op); |
| } |
| |
| def JvmOperation toProxySetter(LDtoAbstractReference prop) { |
| if (prop.toMany) { |
| throw new RuntimeException("toMany-References not allowed for setters!"); |
| } |
| val paramName = prop.toMethodParamName |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toSetterName |
| op.parameters += prop.toParameter(paramName, references.getTypeForName(typeof(ICrossReference), prop)) |
| op.documentation = ''' |
| Sets the proxy of the <code>«paramName»</code> property for lazy cross reference loading. |
| ''' |
| |
| setBody(op, |
| [ // ITreeAppendable |
| if(it == null) return |
| val p = it.trace(prop); |
| p >> prop.toCheckDisposedCall() |
| p >> "firePropertyChange(\"" + paramName + "\", this." + paramName + ", this." + paramName + " = " + |
| paramName + ");" |
| ]) |
| |
| return associate(prop, op); |
| } |
| |
| def JvmOperation toProxyGetter(LDtoAbstractReference prop) { |
| if (prop.toMany) { |
| throw new RuntimeException("toMany-References not allowed for setters!"); |
| } |
| val paramName = prop.toMethodParamName |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(typeof(ICrossReference), prop) |
| op.simpleName = prop.toGetterName |
| op.documentation = ''' |
| Returns the proxy of the <code>«paramName»</code>. |
| ''' |
| |
| setBody(op, |
| [ // ITreeAppendable |
| if(it === null) return |
| val p = it.trace(prop); |
| p >> prop.toCheckDisposedCall() |
| p >> "return " + paramName + ";" |
| ]) |
| |
| return associate(prop, op); |
| } |
| |
| /** |
| * Builds an adder method for a *toMany relation like |
| * <code>Order.addToOrderLines(OrderLine orderLine)</code>. |
| */ |
| def JvmOperation toAdder(LDtoFeature prop, String propertyName) { |
| val paramName = prop.toTypeName.toFirstLower |
| val JvmOperation op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionAdderName |
| if (prop.toDtoTypeReference !== null) { |
| op.parameters += prop.toParameter(paramName, prop.toDtoTypeReference) |
| } |
| |
| op.documentation = ''' |
| Adds the given «paramName» to this object. <p> |
| «IF prop.opposite !== null» |
| Since the reference is a composition reference, the opposite reference <code>«prop.toTypeName»#«prop.opposite.name. |
| toFirstLower»</code> of the <code>«paramName»</code> will be handled automatically and no further coding is required to keep them in sync.<p> |
| See {@link «prop.toTypeName»#«prop.opposite.toSetterName»(«prop.toTypeName»)}. |
| «ENDIF» |
| |
| @param «paramName» - the property |
| @throws RuntimeException if instance is <code>disposed</code> |
| ''' |
| |
| val opposite = prop.opposite |
| op.body = ''' |
| checkDisposed(); |
| |
| «IF opposite != null» |
| «paramName».«prop.opposite.toSetterName»(this); |
| «ELSE» |
| if(!«prop.toCollectionInternalGetterName»().contains(«paramName»)){ |
| «prop.toCollectionInternalAdderName»(«paramName»); |
| } |
| «ENDIF» |
| ''' |
| |
| return associate(prop, op); |
| } |
| |
| /** |
| * Builds an adder method for a *toMany relation like |
| * <code>Order.addToOrderLines(OrderLine orderLine)</code>. |
| */ |
| def JvmOperation toProxyAdder(LDtoAbstractReference prop, String propertyName) { |
| val paramName = prop.toTypeName.toFirstLower |
| val JvmOperation op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionAdderName |
| op.parameters += prop.toParameter(paramName, references.getTypeForName(typeof(ICrossReference), prop)) |
| |
| op.documentation = ''' |
| Adds the cross reference proxy «paramName». <p>''' |
| |
| setBody(op, |
| [ // ITreeAppendable |
| if(it == null) return |
| val p = it.trace(prop); |
| p += prop.toCheckDisposedCall() |
| p >> "if (!" + prop.toGetterName + "().contains(" + paramName + "))" >>> "{" |
| { |
| p >> prop.toGetterName + "().add(" + paramName + ");" |
| } |
| p <<< "}" |
| ]) |
| return associate(prop, op); |
| } |
| |
| def JvmVisibility getInternalMethodVisibility(LDtoFeature ref) { |
| val LPackage ownerPackage = (ref.eContainer() as LType).package; |
| val LPackage refPackage = ref.toRawType.package; |
| if (ownerPackage.equals(refPackage)) { |
| null // package visibility |
| } else { |
| JvmVisibility::PUBLIC |
| } |
| } |
| |
| def dispatch JvmOperation toInternalSetter(LDtoAbstractReference prop) { |
| val paramName = prop.toMethodParamName |
| val typeRef = prop.toDtoTypeReference |
| val JvmOperation result = typesFactory.createJvmOperation(); |
| result.visibility = JvmVisibility::PUBLIC |
| result.returnType = references.getTypeForName(Void::TYPE, prop) |
| result.simpleName = prop.toInternalSetterName |
| result.parameters += prop.toParameter(paramName, typeRef) |
| |
| result.documentation = '''For internal use only!''' |
| |
| setBody(result, |
| [ // ITreeAppendable |
| if(it == null) return |
| val p = it.trace(prop) |
| p >> "firePropertyChange(\"" + paramName + "\", this." + paramName + ", this." + paramName + " = " + |
| paramName + ");" |
| ]) |
| return associate(prop, result); |
| } |
| |
| override JvmField toField(LFeature prop) { |
| val JvmField jvmField = typesFactory.createJvmField(); |
| jvmField.simpleName = prop.toName |
| jvmField.visibility = JvmVisibility::PRIVATE |
| jvmField.type = (prop as LDtoFeature).toDtoTypeReferenceWithMultiplicity |
| jvmField.transient = prop.transient |
| |
| // if uuid |
| if (prop instanceof LAttribute && ((prop as LAttribute).isCreateUuid || (prop as LAttribute).isHistorizedOID)) { |
| jvmField.setInitializer [ |
| if(it == null) return |
| val p = it.trace(prop) |
| p >> '''java.util.UUID.randomUUID().toString()''' |
| ] |
| } |
| |
| annotationCompiler.processAnnotation(prop, jvmField); |
| associate(prop, jvmField); |
| } |
| |
| def boolean isCreateUuid(LAttribute att) { |
| if(att instanceof LDtoInheritedAttribute) { |
| val iAtt = att as LDtoInheritedAttribute |
| return iAtt.inheritedFeature.isUuid |
| }else{ |
| att.isUuid |
| } |
| } |
| |
| def boolean isHistorizedOID(LAttribute att) { |
| if(att instanceof LDtoInheritedAttribute) { |
| val iAtt = att as LDtoInheritedAttribute |
| val feature = iAtt.inheritedFeature |
| if(feature instanceof LEntityFeature) { |
| val entity = feature.entity |
| if((entity.timedependent || entity.historized) && att.toName.equals(Constants::PROP__OID) && |
| entity.uuidPresent) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| def boolean uuidPresent(LEntity entity) { |
| entity.allAttributes.exists[it.uuid] |
| } |
| |
| def JvmField toProxyField(LFeature prop) { |
| val JvmField jvmField = typesFactory.createJvmField(); |
| jvmField.simpleName = prop.toName |
| jvmField.visibility = JvmVisibility::PRIVATE |
| jvmField.type = references.getTypeForName(typeof(ICrossReference), prop) |
| |
| annotationCompiler.processAnnotation(prop, jvmField); |
| associate(prop, jvmField); |
| } |
| |
| def dispatch JvmOperation toInternalSetter(LDtoAbstractAttribute prop) { |
| val paramName = prop.toMethodParamName |
| val typeRef = prop.toDtoTypeReference |
| val JvmOperation result = typesFactory.createJvmOperation(); |
| // result.visibility = getInternalMethodVisibility(prop) |
| result.visibility = JvmVisibility::PUBLIC |
| result.returnType = references.getTypeForName(Void::TYPE, prop) |
| result.simpleName = prop.toInternalSetterName |
| result.parameters += prop.toParameter(paramName, typeRef) |
| |
| result.documentation = '''For internal use only!''' |
| |
| setBody(result, |
| [ // ITreeAppendable |
| if(it == null) return |
| val p = it.trace(prop) |
| p >> "firePropertyChange(\"" + paramName + "\", this." + paramName + ", this." + paramName + " = " + |
| paramName + ");" |
| ]) |
| return associate(prop, result); |
| } |
| |
| def dispatch JvmOperation toInternalAdder(LDtoAbstractReference prop) { |
| val paramName = prop.toTypeName.toFirstLower |
| val typeRef = prop.toDtoTypeReference |
| val JvmOperation op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionInternalAdderName |
| |
| val param = prop.toParameter(paramName, typeRef); |
| if (param != null) { |
| op.parameters += param |
| } |
| |
| op.documentation = '''For internal use only!''' |
| |
| op.body = ''' |
| «IF prop.toRawType.isBean» |
| // add this as property change listener for embeddable beans |
| «paramName».addPropertyChangeListener(this); |
| «ENDIF» |
| |
| if(!«prop.toCollectionInternalGetterName»().contains(«paramName»)) { |
| if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) { |
| // collections will become resolved! We need to send a delta notification. |
| List<«prop.toTypeName»> oldList = new java.util.ArrayList<>(«prop.toCollectionInternalGetterName»()); |
| «prop.toCollectionInternalGetterName»().add(«paramName»); |
| firePropertyChange("«prop.toName»", oldList, «prop.toCollectionInternalGetterName»()); |
| } else { |
| // in mapping mode, we do NOT resolve any collection |
| «prop.toCollectionInternalGetterName»().add(«paramName»); |
| } |
| } |
| ''' |
| return associate(prop, op); |
| } |
| |
| def dispatch JvmOperation toInternalAdder(LDtoAbstractAttribute prop) { |
| val paramName = prop.toTypeName.toFirstLower |
| val typeRef = prop.toDtoTypeReference |
| val JvmOperation op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionInternalAdderName |
| |
| val param = prop.toParameter(paramName, typeRef); |
| if (param != null) { |
| op.parameters += param |
| } |
| |
| op.documentation = '''For internal use only!''' |
| |
| op.body = ''' |
| «IF prop.toRawType.isBean» |
| // add this as property change listener for embeddable beans |
| «paramName».addPropertyChangeListener(this); |
| «ENDIF» |
| List<«prop.toTypeName»> oldList = new java.util.ArrayList<>(«prop.toCollectionInternalGetterName»()); |
| «prop.toCollectionInternalGetterName»().add(«paramName»); |
| firePropertyChange("«prop.toName»", oldList, «prop.toCollectionInternalGetterName»()); |
| ''' |
| |
| return associate(prop, op); |
| } |
| |
| def dispatch JvmOperation toInternalRemover(LDtoAbstractReference prop) { |
| val paramName = prop.toTypeName.toFirstLower |
| val typeRef = prop.toDtoTypeReference |
| val op = typesFactory.createJvmOperation(); |
| // op.visibility = getInternalMethodVisibility(prop) |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionInternalRemoverName |
| |
| val param = prop.toParameter(paramName, typeRef); |
| if (param != null) { |
| op.parameters += param |
| } |
| |
| op.documentation = '''For internal use only!''' |
| |
| op.body = ''' |
| «IF prop.toRawType.isBean» |
| // remove this as property change listener from the embeddable bean |
| «paramName».removePropertyChangeListener(this); |
| «ENDIF» |
| if(!org.eclipse.osbp.dsl.dto.lib.MappingContext.isMappingMode()) { |
| // collections will become resolved! We need to send a delta notification. |
| List<«prop.toTypeName»> oldList = new java.util.ArrayList<>(«prop.toCollectionInternalGetterName»()); |
| «prop.toCollectionInternalGetterName»().remove(«paramName»); |
| firePropertyChange("«prop.toName»", oldList, «prop.toCollectionInternalGetterName»()); |
| }else{ |
| // in mapping mode, we do NOT resolve any collection |
| «prop.toCollectionInternalGetterName»().remove(«paramName»); |
| } |
| ''' |
| |
| return associate(prop, op) |
| } |
| |
| def dispatch JvmOperation toInternalRemover(LDtoAbstractAttribute prop) { |
| val paramName = prop.toTypeName.toFirstLower |
| val typeRef = prop.toDtoTypeReference |
| val op = typesFactory.createJvmOperation(); |
| // op.visibility = getInternalMethodVisibility(prop) |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionInternalRemoverName |
| |
| val param = prop.toParameter(paramName, typeRef); |
| if (param != null) { |
| op.parameters += param |
| } |
| |
| op.documentation = '''For internal use only!''' |
| |
| op.body = ''' |
| «IF prop.toRawType.isBean» |
| // remove this as property change listener from the embeddable bean |
| «paramName».removePropertyChangeListener(this); |
| «ENDIF» |
| List<«prop.toTypeName»> oldList = new java.util.ArrayList<>(«prop.toCollectionInternalGetterName»()); |
| «prop.toCollectionInternalGetterName»().remove(«paramName»); |
| firePropertyChange("«prop.toName»", oldList, «prop.toCollectionInternalGetterName»()); |
| ''' |
| return associate(prop, op) |
| } |
| |
| def dispatch JvmOperation toInternalCollectionGetter(LDtoAbstractReference prop, String name) { |
| val fieldName = name.toFirstLower |
| val JvmOperation op = typesFactory.createJvmOperation() |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = prop.toDtoTypeReferenceWithMultiplicity |
| op.simpleName = prop.toCollectionInternalGetterName |
| op.documentation = ''' |
| Returns the list of «htmlCode(prop.toTypeName)»s thereby lazy initializing it. For internal use only! |
| |
| @return list - the resulting list |
| ''' |
| setBody(op, |
| [ // ITreeAppendable |
| if(it == null) return; |
| var p = it.trace(prop); |
| val fieldRef = "this." + fieldName |
| p >> "if (" + fieldRef + " == null)" >>> " {" |
| { |
| p >> fieldRef >> " = new java.util.ArrayList<" + prop.toTypeName + ">();" |
| } |
| p <<< "}" |
| p >> "return " + fieldRef + ";" |
| ]) |
| prop.associate(op) |
| } |
| |
| def dispatch JvmOperation toInternalCollectionGetter(LDtoAbstractAttribute prop, String name) { |
| val fieldName = name.toFirstLower |
| val JvmOperation op = typesFactory.createJvmOperation() |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = prop.toDtoTypeReferenceWithMultiplicity |
| op.simpleName = prop.toCollectionInternalGetterName |
| op.documentation = ''' |
| Returns the list of «htmlCode(prop.toTypeName)»s thereby lazy initializing it. For internal use only! |
| |
| @return list - the resulting list |
| ''' |
| setBody(op, |
| [ // ITreeAppendable |
| if(it == null) return; |
| var p = it.trace(prop); |
| val fieldRef = "this." + fieldName |
| p >> "if (" + fieldRef + " == null)" >>> " {" |
| { |
| p >> fieldRef >> " = new java.util.ArrayList<" + prop.toDtoTypeReference.qualifiedName + ">();" |
| } |
| p <<< "}" |
| p >> "return " + fieldRef + ";" |
| ]) |
| prop.associate(op) |
| } |
| |
| /** |
| * Builds a remover method for a *toMany relation like |
| * <code>Order.removeFromOrderLines(OrderLine orderLine)</code>. |
| */ |
| def dispatch JvmOperation toRemover(LDtoAbstractReference prop, String propertyName) { |
| val paramName = prop.toTypeName.toFirstLower |
| val JvmOperation op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionRemoverName |
| if (prop.toDtoTypeReference != null) { |
| op.parameters += prop.toParameter(paramName, prop.toDtoTypeReference) |
| } |
| if (prop.opposite != null) { |
| op.documentation = ''' |
| Removes the given «paramName» from this object. <p> |
| «IF prop.cascading» |
| Since the reference is a cascading reference, the opposite reference («prop.toTypeName».«prop.opposite.name. |
| toFirstLower») |
| of the «paramName» will be handled automatically and no further coding is required to keep them in sync. |
| See {@link «prop.toTypeName»#«prop.opposite.toSetterName»(«prop.toTypeName»)}. |
| «ENDIF» |
| |
| @param «paramName» - the property |
| @throws RuntimeException if instance is <code>disposed</code> |
| ''' |
| } |
| |
| val opposite = prop.opposite |
| val cascading = prop.isCascading |
| op.body = ''' |
| checkDisposed(); |
| |
| «IF opposite != null» |
| «paramName».«prop.opposite.toSetterName»(null); |
| «ELSE» |
| «prop.toCollectionInternalRemoverName»(«paramName»); |
| «ENDIF» |
| ''' |
| |
| // setBody(op, |
| // [ // ITreeAppendable |
| // if(it == null) return |
| // val p = it.trace(prop); |
| // p += prop.toCheckDisposedCall() |
| // if (prop.opposite != null) { |
| // p >> "if (isCopy())" >>> "{" |
| // p >>> "// avoid opposite reference update" |
| // p >> prop.toCollectionInternalGetterName + "().remove(" + paramName + ");" |
| // p <<< "} else {" |
| // p >>> paramName + "." + prop.opposite.toSetterName + "(null);" |
| // p <<< "}" |
| // } else { |
| // p >> prop.toCollectionInternalGetterName + "().remove(" + paramName + ");" |
| // } |
| // ]) |
| return associate(prop, op); |
| } |
| |
| def JvmOperation toProxyRemover(LDtoAbstractReference prop, String propertyName) { |
| val paramName = prop.toTypeName.toFirstLower |
| val JvmOperation op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionRemoverName |
| op.parameters += prop.toParameter(paramName, references.getTypeForName(typeof(ICrossReference), prop)) |
| op.documentation = ''' |
| Removes the proxy cross reference «paramName» from this object. <p> |
| ''' |
| setBody(op, |
| [ // ITreeAppendable |
| if(it == null) return |
| val p = it.trace(prop); |
| p += prop.toCheckDisposedCall() |
| p >> prop.toGetterName + "().remove(" + paramName + ");" |
| ]) |
| return associate(prop, op); |
| } |
| |
| /** |
| * Builds a remover method for a *toMany relation like |
| * <code>Order.removeFromOrderLines(OrderLine orderLine)</code>. |
| */ |
| def dispatch JvmOperation toRemover(LDtoAbstractAttribute prop, String propertyName) { |
| val paramName = prop.toTypeName.toFirstLower |
| val JvmOperation op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, prop) |
| op.simpleName = prop.toCollectionRemoverName |
| if (prop.toDtoTypeReference != null) { |
| op.parameters += prop.toParameter(paramName, prop.toDtoTypeReference) |
| } |
| if (prop.opposite != null) { |
| op.documentation = ''' |
| Removes the given «paramName» from this object. <p> |
| «IF prop.cascading» |
| Since the reference is a cascading reference, the opposite reference <code>«prop.toTypeName».«prop.opposite.name. |
| toFirstLower»</code> of the <code>«paramName»</code> will be handled automatically and no further coding is required to keep them in sync. |
| See {@link «prop.toTypeName»#«prop.opposite.toSetterName»(«prop.toTypeName»)}. |
| «ENDIF» |
| |
| @param «paramName» - the property |
| @throws RuntimeException if instance is <code>disposed</code> |
| ''' |
| } else { |
| } |
| val opposite = prop.opposite |
| val cascading = prop.isCascading |
| op.body = ''' |
| checkDisposed(); |
| |
| «IF opposite != null» |
| «paramName».«prop.opposite.toSetterName»(null); |
| «ELSE» |
| «prop.toCollectionInternalRemoverName»(«paramName»); |
| «ENDIF» |
| ''' |
| return associate(prop, op); |
| } |
| |
| def JvmOperation toMapperBindMethod(LDto dto) { |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| op.returnType = references.getTypeForName(Void::TYPE, dto) |
| op.simpleName = "bindMapperAccess" |
| op.parameters += dto.toParameter("mapperAccess", references.getTypeForName(typeof(IMapperAccess), dto, null)) |
| op.documentation = ''' |
| Called by OSGi-DS. Binds the mapper access service. |
| |
| @param service - The mapper access service |
| '''; |
| |
| op.body = ''' |
| this.mapperAccess = mapperAccess; |
| ''' |
| return associate(dto, op); |
| } |
| |
| def JvmOperation toMapperUnbindMethod(LDto dto) { |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| op.returnType = references.getTypeForName(Void::TYPE, dto) |
| op.simpleName = "unbindMapperAccess" |
| op.parameters += dto.toParameter("mapperAccess", references.getTypeForName(typeof(IMapperAccess), dto, null)) |
| op.documentation = ''' |
| Called by OSGi-DS. Binds the mapper access service. |
| |
| @param service - The mapper access service |
| '''; |
| |
| op.body = ''' |
| this.mapperAccess = null; |
| ''' |
| return associate(dto, op); |
| } |
| |
| def JvmField toMapperField(LDtoAbstractReference prop) { |
| val JvmField jvmField = typesFactory.createJvmField(); |
| jvmField.simpleName = prop.toMapperFieldName |
| jvmField.visibility = JvmVisibility::PRIVATE |
| jvmField.type = cloneWithProxies(prop.type.toMapperTypeReference) |
| |
| annotationCompiler.processAnnotation(prop, jvmField); |
| associate(prop, jvmField); |
| } |
| |
| def JvmOperation toGetToDtoMapperAccess(LDto dto) { |
| |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| |
| val dTypeParam = typesFactory.createJvmTypeParameter |
| dTypeParam.setName("D") |
| op.typeParameters += dTypeParam |
| val eTypeParam = typesFactory.createJvmTypeParameter |
| eTypeParam.name = "E" |
| op.typeParameters += eTypeParam |
| |
| val dType = typesFactory.createJvmGenericType("D") |
| val dTypeRef = typesFactory.createJvmParameterizedTypeReference() |
| dTypeRef.type = dType |
| val eType = typesFactory.createJvmGenericType("E") |
| val eTypeRef = typesFactory.createJvmParameterizedTypeReference() |
| eTypeRef.type = eType |
| |
| op.returnType = references.getTypeForName(typeof(IMapper), dto, dTypeRef.cloneWithProxies, |
| eTypeRef.cloneWithProxies) |
| op.simpleName = "getToDtoMapper" |
| op.parameters += |
| dto.toParameter("dtoClass", references.getTypeForName(typeof(Class), dto, dTypeRef.cloneWithProxies)) |
| op.parameters += |
| dto.toParameter("entityClass", references.getTypeForName(typeof(Class), dto, eTypeRef.cloneWithProxies)) |
| |
| op.documentation = ''' |
| Returns the mapper instance that may map between the given dto and entity. Or <code>null</code> if no mapper is available. |
| |
| @param dtoClass - the class of the dto that should be mapped |
| @param entityClass - the class of the entity that should be mapped |
| @return the mapper instance or <code>null</code>''' |
| |
| op.body = ''' |
| return mapperAccess.getToDtoMapper(dtoClass, entityClass); |
| ''' |
| return associate(dto, op); |
| } |
| |
| def JvmOperation toGetToEntityMapperAccess(LDto dto) { |
| |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| |
| val dTypeParam = typesFactory.createJvmTypeParameter |
| dTypeParam.setName("D") |
| op.typeParameters += dTypeParam |
| val eTypeParam = typesFactory.createJvmTypeParameter |
| eTypeParam.name = "E" |
| op.typeParameters += eTypeParam |
| |
| val dType = typesFactory.createJvmGenericType("D") |
| val dTypeRef = typesFactory.createJvmParameterizedTypeReference() |
| dTypeRef.type = dType |
| val eType = typesFactory.createJvmGenericType("E") |
| val eTypeRef = typesFactory.createJvmParameterizedTypeReference() |
| eTypeRef.type = eType |
| |
| op.returnType = references.getTypeForName(typeof(IMapper), dto, dTypeRef.cloneWithProxies, |
| eTypeRef.cloneWithProxies) |
| op.simpleName = "getToEntityMapper" |
| op.parameters += |
| dto.toParameter("dtoClass", references.getTypeForName(typeof(Class), dto, dTypeRef.cloneWithProxies)) |
| op.parameters += |
| dto.toParameter("entityClass", references.getTypeForName(typeof(Class), dto, eTypeRef.cloneWithProxies)) |
| |
| op.documentation = ''' |
| Returns the mapper instance that may map between the given dto and entity. Or <code>null</code> if no mapper is available. |
| |
| @param dtoClass - the class of the dto that should be mapped |
| @param entityClass - the class of the entity that should be mapped |
| @return the mapper instance or <code>null</code>''' |
| |
| op.body = ''' |
| return mapperAccess.getToEntityMapper(dtoClass, entityClass); |
| ''' |
| return associate(dto, op); |
| } |
| |
| def JvmOperation toMapToDto(LDto dto) { |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, dto) |
| op.simpleName = "mapToDTO" |
| op.parameters += dto.toParameter("dto", dto.findDtoTypeReference) |
| op.parameters += dto.toParameter("entity", dto.wrappedType?.toTypeReference) |
| op.parameters += dto.toParameter("context", references.getTypeForName(typeof(MappingContext), dto)) |
| op.documentation = ''' |
| Maps the entity {@link «dto.wrappedType.toName»} to the dto {@link «dto.toName»}. |
| |
| @param dto - The target dto |
| @param entity - The source entity |
| @param context - The context to get information about depth,... |
| '''; |
| |
| op.body = ''' |
| if(context == null){ |
| throw new IllegalArgumentException("Please pass a context!"); |
| } |
| «IF !dto.wrappedType.isBean» |
| context.register(createDtoHash(entity), dto); |
| |
| «ENDIF» |
| «IF dto.superType != null» |
| super.mapToDTO(dto, entity, context); |
| |
| «ENDIF» |
| «FOR f : dto.features.filter[inherited || mapper?.toDTO != null]» |
| «IF (!f.bounds.toMany)» |
| ««« Do not map containerreference by default -> Causes Loop!» |
| ««« «IF f.isContainerReference» |
| ««« if(dto.get«f.toName.toFirstUpper»() == null) { |
| ««« // «f.toName» is container property. So check for null to avoid looping |
| ««« dto.set«f.toName.toFirstUpper»(«f.toMapPropertyToDto»(entity, context)); |
| ««« } |
| ««« «ELSE» |
| dto.set«f.toName.toFirstUpper»(«f.toMapPropertyToDto»(entity, context)); |
| ««« «ENDIF» |
| «ELSE» |
| ««« REPLACED BY installLazyCollections if(dto.«f.toGetterName»().isEmpty()) { |
| ««« for(«f.toDtoTypeReference.qualifiedName» _dtoValue : «f.toMapPropertyToDto»(entity, context)) { |
| ««« dto.«f.toCollectionAdderName»(_dtoValue); |
| ««« } |
| ««« } |
| «ENDIF» |
| «ENDFOR» |
| ''' |
| return associate(dto, op); |
| } |
| |
| def JvmOperation toInstallLazyCollections(LDto dto) { |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| op.returnType = references.getTypeForName(Void::TYPE, dto) |
| op.simpleName = "installLazyCollections" |
| op.documentation = ''' |
| Installs lazy collection resolving for entity {@link «dto.wrappedType.toName»} to the dto {@link «dto.toName»}. |
| '''; |
| |
| op.body = ''' |
| «IF dto.superType !== null» |
| super.installLazyCollections(); |
| «ENDIF» |
| «FOR f : dto.references.filter[inherited && !dto.wrappedType.isBean]» |
| «IF (f.bounds.toMany)» |
| «IF (f.isContainmentReference)» |
| «f.toName» = new org.eclipse.osbp.dsl.dto.lib.OppositeContainmentDtoList<>( |
| org.eclipse.osbp.dsl.dto.lib.MappingContext.getCurrent(), |
| «f.toDtoTypeReference.simpleName».class, this, "«f.opposite.name».«(f.opposite as LReference).toDtoIdAttribute»", |
| (java.util.function.Supplier<Object> & Serializable) () -> this.get«dto.idAttribute.name.toFirstUpper»(), this); |
| «ELSE» |
| «f.toName» = new org.eclipse.osbp.dsl.dto.lib.OppositeDtoList<>( |
| org.eclipse.osbp.dsl.dto.lib.MappingContext.getCurrent(), |
| «f.toDtoTypeReference.simpleName».class, "«f.opposite.name».«(f.opposite as LReference).toDtoIdAttribute»", |
| (java.util.function.Supplier<Object> & Serializable) () -> this.get«dto.idAttribute.name.toFirstUpper»(), this); |
| «ENDIF» |
| «ENDIF» |
| «ENDFOR» |
| ''' |
| return associate(dto, op); |
| } |
| |
| def String toDtoIdAttribute(LReference ref) { |
| ref.toRawType.idAttribute.name |
| } |
| |
| def JvmOperation toFirePropertyChange(LClass sourceElement, boolean useVersion) { |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.simpleName = "firePropertyChange" |
| op.returnType = references.getTypeForName(Void::TYPE, sourceElement, null) |
| op.parameters += |
| sourceElement.toParameter("propertyName", references.getTypeForName(typeof(String), sourceElement, null)) |
| op.parameters += sourceElement.toParameter("oldValue", |
| references.getTypeForName(typeof(Object), sourceElement, null)) |
| op.parameters += sourceElement.toParameter("newValue", |
| references.getTypeForName(typeof(Object), sourceElement, null)) |
| |
| op.documentation = ''' |
| @see PropertyChangeSupport#firePropertyChange(String, Object, Object)''' |
| |
| setBody(op, ''' |
| propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); |
| ''') |
| |
| associate(sourceElement, op) |
| } |
| |
| def JvmOperation toMapToEntity(LDto dto) { |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PUBLIC |
| op.returnType = references.getTypeForName(Void::TYPE, dto) |
| op.simpleName = "mapToEntity" |
| op.parameters += dto.toParameter("dto", dto.findDtoTypeReference) |
| op.parameters += dto.toParameter("entity", dto.wrappedType?.toTypeReference) |
| op.parameters += dto.toParameter("context", references.getTypeForName(typeof(MappingContext), dto)) |
| op.documentation = ''' |
| Maps the dto {@link «dto.toName»} to the entity {@link «dto.wrappedType.toName»}. |
| |
| @param dto - The source dto |
| @param entity - The target entity |
| @param context - The context to get information about depth,... |
| '''; |
| |
| op.body = ''' |
| if(context == null){ |
| throw new IllegalArgumentException("Please pass a context!"); |
| } |
| |
| «IF !dto.wrappedType.isBean» |
| context.register(createEntityHash(dto), entity); |
| context.registerMappingRoot(createEntityHash(dto), dto); |
| «ENDIF» |
| «IF dto.superType != null» |
| super.mapToEntity(dto, entity, context); |
| «ENDIF» |
| |
| «FOR f : dto.features.filter[inherited || mapper?.fromDTO != null]» |
| «IF!f.bounds.toMany» |
| «IF !f.derived» |
| entity.set«f.toName.toFirstUpper»(«f.toMapPropertyToEntity»(dto, entity, context)); |
| «ENDIF» |
| «ELSE» |
| «f.toMapPropertyToEntity»(dto, entity, context); |
| «ENDIF» |
| «ENDFOR» |
| ''' |
| |
| return associate(dto, op); |
| } |
| |
| // def JvmOperation toMapToDtoProperty(LDtoFeature prop) { |
| // val LDto dto = prop.eContainer as LDto |
| // val op = typesFactory.createJvmOperation(); |
| // op.visibility = JvmVisibility::PROTECTED |
| // op.returnType = references.getTypeForName(Void::TYPE, prop) |
| // op.simpleName = prop.toMapPropertyToDto |
| // |
| // associate(prop, op); |
| // |
| // initializeSafely(op) [ |
| // parameters += prop.toParameter("dto", dto.wrappedType.toTypeReference) |
| // parameters += prop.toParameter("entity", dto.toTypeReference) |
| // documentation = ''' |
| // Maps the property «prop.toName» to the given entity to the given dto. |
| // |
| // @param dto - The target dto |
| // @param entity - The source entity |
| // '''; |
| // val XExpression mapExpression = prop.toMapToDtoExpression |
| // if (mapExpression != null) { |
| // body = mapExpression |
| // } else { |
| // body = [] |
| // } |
| // ] |
| // } |
| // |
| // def JvmOperation toMapToEntityProperty(LDtoFeature prop) { |
| // val LDto dto = prop.eContainer as LDto |
| // |
| // val op = typesFactory.createJvmOperation(); |
| // op.visibility = JvmVisibility::PROTECTED |
| // op.returnType = references.getTypeForName(Void::TYPE, prop) |
| // op.simpleName = prop.toMapPropertyToEntity |
| // |
| // associate(prop, op); |
| // |
| // initializeSafely(op) [ |
| // parameters += op.toParameter("in", dto.toTypeReference) |
| // parameters += op.toParameter("out", dto.wrappedType.toTypeReference) |
| // documentation = ''' |
| // Maps the property «prop.toName» from the given dto to the given entity. |
| // |
| // @param dto - The source dto |
| // @param entity - The target entity |
| // ''' |
| // val mapExpression = prop.toMapToEntityExpression |
| // associate(prop, mapExpression) |
| // if (mapExpression != null) { |
| // body = mapExpression |
| // } else { |
| // body = [] |
| // } |
| // ] |
| // |
| // } |
| /** |
| * returns the mapper class type |
| */ |
| def JvmGenericType toMapperJvmType(LDto lDto) { |
| val type = createJvmGenericType(lDto, lDto.toFqnMapperName) |
| associate(lDto, type) |
| } |
| |
| def dispatch JvmOperation toMapToDtoProperty(LDtoAbstractAttribute prop) { |
| val LDto dto = prop.eContainer as LDto |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| op.returnType = prop.toDtoTypeReferenceWithMultiplicity |
| op.simpleName = prop.toMapPropertyToDto |
| |
| associate(prop, op); |
| |
| initializeSafely(op) [ |
| parameters += prop.toParameter("in", dto.wrappedType?.toTypeReference) |
| parameters += prop.toParameter("context", references.getTypeForName(typeof(MappingContext), prop)) |
| documentation = ''' |
| Maps the property «prop.toName» from the given entity to dto property. |
| |
| @param in - The source entity |
| @param context - The context to get information about depth,... |
| @return the mapped value |
| '''; |
| val XExpression mapExpression = prop.toMapToDtoExpression |
| if (mapExpression != null) { |
| body = mapExpression |
| } else { |
| if (prop.toRawType instanceof LBean) { |
| if (prop.bounds.toMany) { |
| body = ''' |
| org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toRawType.toDTOBeanSimpleName», «prop.toRawType.toName»> mapper = getToDtoMapper(«prop.toRawType.toDTOBeanSimpleName».class, «prop.toRawType.toName».class); |
| if(mapper == null) { |
| throw new IllegalStateException("Mapper must not be null!"); |
| } |
| |
| if (context.isDetectRecursion(«prop.toRawType.toDTOBeanSimpleName».class)) { |
| return java.util.Collections.emptyList(); |
| } |
| |
| context.increaseLevel(); |
| List<«prop.toRawType.toDTOBeanSimpleName»> results = new java.util.ArrayList<«prop.toRawType.toDTOBeanSimpleName»>(); |
| for («prop.toRawType.toName» _entity : in.«prop.toGetterName»()) { |
| «prop.toDtoTypeReference.qualifiedName» _dto = context.get(mapper.createDtoHash(_entity)); |
| if (_dto == null) { |
| _dto = mapper.createDto(); |
| mapper.mapToDTO(_dto, _entity, context); |
| } else { |
| if(context.isRefresh()){ |
| mapper.mapToDTO(_dto, _entity, context); |
| } |
| } |
| results.add(_dto); |
| } |
| context.decreaseLevel(); |
| return results;''' |
| } else { |
| body = ''' |
| if(in.get«prop.toName.toFirstUpper»() != null) { |
| // find a mapper that knows how to map the concrete input type. |
| org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toRawType.toDTOBeanSimpleName», «prop.toRawType.toName»> mapper = (org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toRawType.toDTOBeanSimpleName», «prop.toRawType.toName»>) getToDtoMapper(«prop.toRawType.toDTOBeanSimpleName».class, in.get«prop.toName.toFirstUpper»().getClass()); |
| if(mapper == null) { |
| throw new IllegalStateException("Mapper must not be null!"); |
| } |
| |
| «prop.toRawType.toDTOBeanSimpleName» dto = null; |
| «IF !prop.toRawType.isBean» |
| dto = context.get(mapper.createDtoHash(in.«prop.toGetterName»())); |
| if(dto != null) { |
| if(context.isRefresh()){ |
| mapper.mapToDTO(dto, in.«prop.toGetterName»(), context); |
| } |
| return dto; |
| } |
| |
| «ENDIF» |
| context.increaseLevel(); |
| dto = mapper.createDto(); |
| mapper.mapToDTO(dto, in.«prop.toGetterName»(), context); |
| context.decreaseLevel(); |
| return dto; |
| } else { |
| return null; |
| } |
| ''' |
| } |
| } else { |
| if (prop.typeIsBoolean) { |
| body = '''return in.is«prop.toName.toFirstUpper»();''' |
| } else if(prop.typeIsEnum) { |
| body = ''' |
| if(in.get«prop.toName.toFirstUpper»() != null) { |
| return «prop.toRawType.toDTOEnumFullyQualifiedName».valueOf(in.get«prop.toName.toFirstUpper»().name()); |
| } else { |
| return null; |
| } |
| ''' |
| } else { |
| body = '''return in.get«prop.toName.toFirstUpper»();''' |
| } |
| } |
| } |
| ] |
| } |
| |
| def dispatch JvmOperation toMapToDtoProperty(LDtoAbstractReference prop) { |
| val LDto dto = prop.eContainer as LDto |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| op.returnType = prop.toDtoTypeReferenceWithMultiplicity |
| |
| op.simpleName = prop.toMapPropertyToDto |
| |
| associate(prop, op); |
| |
| initializeSafely(op) [ |
| parameters += prop.toParameter("in", dto.wrappedType?.toTypeReference) |
| parameters += prop.toParameter("context", references.getTypeForName(typeof(MappingContext), prop)) |
| documentation = ''' |
| Maps the property «prop.toName» from the given entity to the dto. |
| |
| @param in - The source entity |
| @param context - The context to get information about depth,... |
| @return «IF (!prop.bounds.toMany)»the mapped dto«ELSE»A list of mapped dtos«ENDIF» |
| '''; |
| val XExpression mapExpression = prop.toMapToDtoExpression |
| if (mapExpression != null) { |
| body = mapExpression |
| } else { |
| if (prop.bounds.toMany) { |
| body = ''' |
| ««« org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toTypeName», «prop.toRawType.toName»> mapper = getToDtoMapper(«prop.toTypeName».class, «prop.toRawType.toName».class); |
| ««« if(mapper == null) { |
| ««« throw new IllegalStateException("Mapper must not be null!"); |
| ««« } |
| ««« |
| ««« if (context.isDetectRecursion(«prop.toTypeName».class)) { |
| ««« return java.util.Collections.emptyList(); |
| ««« } |
| ««« |
| ««« context.increaseLevel(); |
| ««« List<«prop.toTypeName»> results = new java.util.ArrayList<«prop.toTypeName»>(); |
| ««« for («prop.toRawType.toName» _entity : in.get«prop.toName.toFirstUpper»()) { |
| ««« «prop.toTypeName» _dto = context.get(mapper.createDtoHash(_entity)); |
| ««« if (_dto == null) { |
| ««« _dto = mapper.createDto(); |
| ««« mapper.mapToDTO(_dto, _entity, context); |
| ««« } else { |
| ««« if(context.isRefresh()){ |
| ««« mapper.mapToDTO(_dto, _entity, context); |
| ««« } |
| ««« } |
| ««« results.add(_dto); |
| ««« } |
| ««« context.decreaseLevel(); |
| // nothing to do here. Mapping is done by OppositeLists |
| return null;''' |
| } else { |
| body = ''' |
| if(in.get«prop.toName.toFirstUpper»() != null) { |
| // find a mapper that knows how to map the concrete input type. |
| org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toTypeName», «prop.toRawType.toName»> mapper = (org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toTypeName», «prop.toRawType.toName»>) getToDtoMapper(«prop.toTypeName».class, in.get«prop.toName.toFirstUpper»().getClass()); |
| if(mapper == null) { |
| throw new IllegalStateException("Mapper must not be null!"); |
| } |
| «prop.toTypeName» dto = null; |
| «IF !prop.toRawType.isBean» |
| dto = context.get(mapper.createDtoHash(in.get«prop.toName.toFirstUpper»())); |
| if(dto != null) { |
| if(context.isRefresh()){ |
| mapper.mapToDTO(dto, in.«prop.toGetterName»(), context); |
| } |
| return dto; |
| } |
| |
| «ENDIF» |
| context.increaseLevel(); |
| dto = mapper.createDto(); |
| mapper.mapToDTO(dto, in.get«prop.toName.toFirstUpper»(), context); |
| context.decreaseLevel(); |
| return dto; |
| } else { |
| return null; |
| } |
| ''' |
| } |
| } |
| ] |
| } |
| |
| def JvmGenericType findJvmType(LDto lDto){ |
| return (associator as IJvmModelAssociations).getPrimaryJvmElement(lDto) as JvmGenericType |
| } |
| |
| def dispatch JvmOperation toMapToEntityProperty(LDtoAbstractAttribute prop) { |
| val LDto dto = prop.eContainer as LDto |
| |
| // TODO change all stuff like this |
| val JvmGenericType dtoJvmType = dto.findJvmType |
| |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| op.returnType = prop.toRawTypeReferenceWithMultiplicity |
| op.simpleName = prop.toMapPropertyToEntity |
| |
| associate(prop, op); |
| |
| initializeSafely(op) [ |
| // TODO find typeref in sames resource! |
| parameters += prop.toParameter("in", dtoJvmType.newTypeRef(null)) |
| parameters += prop.toParameter("parentEntity", dto.wrappedType?.toTypeReference) |
| parameters += prop.toParameter("context", references.getTypeForName(typeof(MappingContext), prop)) |
| documentation = ''' |
| Maps the property «prop.toName» from the given entity to dto property. |
| |
| @param in - The source entity |
| @param parentEntity - The parentEntity |
| @param context - The context to get information about depth,... |
| @return the mapped value |
| '''; |
| val XExpression mapExpression = prop.toMapToEntityExpression |
| if (mapExpression != null) { |
| body = mapExpression |
| } else { |
| if (prop.toRawType instanceof LBean) { |
| if (prop.bounds.toMany) { |
| body = ''' |
| org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toRawType.toDTOBeanSimpleName», «prop.toRawType.toName»> mapper = getToEntityMapper(«prop.toRawType.toDTOBeanSimpleName».class, «prop.toRawType.toName».class); |
| if(mapper == null) { |
| throw new IllegalStateException("Mapper must not be null!"); |
| } |
| |
| List<«prop.toRawType.toName»> results = new java.util.ArrayList<«prop.toRawType.toName»>(); |
| for («prop.toRawType.toDTOBeanSimpleName» _dto : in.«prop.toGetterName»()) { |
| «prop.toRawType.toName» _entity = mapper.createEntity(); |
| mapper.mapToEntity(_dto, _entity, context); |
| results.add(_entity); |
| } |
| return results;''' |
| } else { |
| body = ''' |
| if(in.get«prop.toName.toFirstUpper»() != null) { |
| // find a mapper that knows how to map the concrete input type. |
| org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toRawType.toDTOBeanSimpleName», «prop.toRawType.toName»> mapper = (org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toRawType.toDTOBeanSimpleName», «prop.toRawType.toName»>) getToEntityMapper(in.get«prop.toName.toFirstUpper»().getClass(), «prop.toRawType.toName».class); |
| if(mapper == null) { |
| throw new IllegalStateException("Mapper must not be null!"); |
| } |
| |
| «prop.toRawType.toName» entity = mapper.createEntity(); |
| mapper.mapToEntity(in.«prop.toGetterName»(), entity, context); |
| return entity; |
| } else { |
| return null; |
| }''' |
| } |
| } else { |
| if (prop.typeIsBoolean) { |
| body = '''return in.is«prop.toName.toFirstUpper»();''' |
| } else if(prop.typeIsEnum) { |
| body = ''' |
| if(in.get«prop.toName.toFirstUpper»() != null) { |
| return «prop.toRawType.fullyQualifiedName.toString».valueOf(in.get«prop.toName.toFirstUpper»().name()); |
| } else { |
| return null; |
| } |
| ''' |
| } else { |
| body = '''return in.get«prop.toName.toFirstUpper»();''' |
| } |
| } |
| } |
| ] |
| } |
| |
| def dispatch JvmOperation toMapToEntityProperty(LDtoAbstractReference prop) { |
| val LDto dto = prop.eContainer as LDto |
| val op = typesFactory.createJvmOperation(); |
| op.visibility = JvmVisibility::PROTECTED |
| op.returnType = prop.toRawTypeReferenceWithMultiplicity |
| op.simpleName = prop.toMapPropertyToEntity |
| |
| associate(prop, op); |
| |
| initializeSafely(op) [ |
| parameters += prop.toParameter("in", dto.findDtoTypeReference) |
| parameters += prop.toParameter("parentEntity", dto.wrappedType?.toTypeReference) |
| parameters += prop.toParameter("context", references.getTypeForName(typeof(MappingContext), prop)) |
| documentation = ''' |
| Maps the property «prop.toName» from the given dto to the entity. |
| |
| @param in - The source dto |
| @param parentEntity - The parent entity |
| @param context - The context to get information about depth,... |
| @return «IF (!prop.bounds.toMany)»the mapped entity«ELSE»A list of mapped entities«ENDIF» |
| '''; |
| val XExpression mapExpression = prop.toMapToEntityExpression |
| if (mapExpression != null) { |
| body = mapExpression |
| } else { |
| if (prop.bounds.toMany) { |
| body = ''' |
| org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toTypeName», «prop.toRawType.toName»> mapper = getToEntityMapper(«prop.toTypeName».class, «prop.toRawType.toName».class); |
| if(mapper == null) { |
| throw new IllegalStateException("Mapper must not be null!"); |
| } |
| |
| org.eclipse.osbp.dsl.dto.lib.IEntityMappingList<«prop.toTypeName»> childsList = |
| (org.eclipse.osbp.dsl.dto.lib.IEntityMappingList<«prop.toTypeName»>) in.internalGet«prop.toName.toFirstUpper»(); |
| |
| // if entities are being added, then they are passed to |
| // #addToContainerChilds of the parent entity. So the container ref is setup |
| // properly! |
| // if entities are being removed, then they are passed to the |
| // #internalRemoveFromChilds method of the parent entity. So they are |
| // removed directly from the list of entities. |
| childsList.mapToEntity(mapper, |
| parentEntity::addTo«prop.toName.toFirstUpper», |
| parentEntity::internalRemoveFrom«prop.toName.toFirstUpper»); |
| return null; |
| ''' |
| } else { |
| body = ''' |
| if(in.get«prop.toName.toFirstUpper»() != null) { |
| // find a mapper that knows how to map the concrete input type. |
| org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toTypeName», «prop.toRawType.toName»> mapper = (org.eclipse.osbp.dsl.dto.lib.IMapper<«prop.toTypeName», «prop.toRawType.toName»>) getToEntityMapper(in.get«prop.toName.toFirstUpper»().getClass(), «prop.toRawType.toName».class); |
| if(mapper == null) { |
| throw new IllegalStateException("Mapper must not be null!"); |
| } |
| |
| «prop.toRawType.toName» entity = null; |
| «IF !prop.toRawType.isBean» |
| entity = context.get(mapper.createEntityHash(in.get«prop.toName.toFirstUpper»())); |
| if(entity != null) { |
| return entity; |
| } else { |
| entity = («prop.toRawType.toName») context |
| .findEntityByEntityManager(«prop.toRawType.toName».class, in.get«prop.toName.toFirstUpper»().get«prop.toRawType.idAttribute.toName.toFirstUpper»()); |
| if (entity != null) { |
| context.register(mapper.createEntityHash(in.get«prop.toName.toFirstUpper»()), entity); |
| return entity; |
| } |
| } |
| |
| «ENDIF» |
| entity = mapper.createEntity(); |
| mapper.mapToEntity(in.get«prop.toName.toFirstUpper»(), entity, context); |
| return entity; |
| } else { |
| return null; |
| } |
| ''' |
| } |
| } |
| ] |
| } |
| |
| def findDtoTypeReference(LDto dto){ |
| return getByPostfix(dto, "Dto").newTypeRef(null) |
| } |
| |
| def findDtoMapperTypeReference(LDto dto){ |
| return getByPostfix(dto, "DtoMapper").newTypeRef(null) |
| } |
| |
| def findSuperDtoMapperType(LDto dto, JvmTypeReference dtoType, JvmTypeReference entityType){ |
| var type = getByPostfix(dto.superType, "DtoMapper") |
| if(type == null) { |
| var superTypeFQN = dto.superType.fullyQualifiedName |
| superTypeFQN = superTypeFQN.append("Mapper") |
| val List<String> list = newArrayList() |
| list.addAll(superTypeFQN.segments) |
| list.add(list.size - 1, "mapper") |
| |
| val mapperFQN = QualifiedName.create(list) |
| val JvmParameterizedTypeReference ref = references.getTypeForName(mapperFQN.toString, dto, null) as JvmParameterizedTypeReference |
| ref.arguments += dtoType |
| ref.arguments += entityType |
| return ref |
| }else{ |
| val JvmParameterizedTypeReference ref = type.newTypeRef(null) as JvmParameterizedTypeReference |
| ref.arguments.clear |
| ref.arguments += dtoType |
| ref.arguments += entityType |
| return ref |
| } |
| } |
| } |