diff --git a/core/out/production/classes/eu/mihosoft/vmf/VMF.class b/core/out/production/classes/eu/mihosoft/vmf/VMF.class new file mode 100644 index 00000000..9da7f3a6 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/VMF.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Annotation.class b/core/out/production/classes/eu/mihosoft/vmf/core/Annotation.class new file mode 100644 index 00000000..0cd762e8 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Annotation.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/AnnotationInfo.class b/core/out/production/classes/eu/mihosoft/vmf/core/AnnotationInfo.class new file mode 100644 index 00000000..2e62b7b9 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/AnnotationInfo.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Annotations.class b/core/out/production/classes/eu/mihosoft/vmf/core/Annotations.class new file mode 100644 index 00000000..b25538ed Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Annotations.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/CodeGenerator.class b/core/out/production/classes/eu/mihosoft/vmf/core/CodeGenerator.class new file mode 100644 index 00000000..3b30716e Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/CodeGenerator.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/CollectionType.class b/core/out/production/classes/eu/mihosoft/vmf/core/CollectionType.class new file mode 100644 index 00000000..02438bef Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/CollectionType.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Container.class b/core/out/production/classes/eu/mihosoft/vmf/core/Container.class new file mode 100644 index 00000000..b90d6b3b Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Container.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ContainmentInfo.class b/core/out/production/classes/eu/mihosoft/vmf/core/ContainmentInfo.class new file mode 100644 index 00000000..c4a44b1b Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ContainmentInfo.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ContainmentType.class b/core/out/production/classes/eu/mihosoft/vmf/core/ContainmentType.class new file mode 100644 index 00000000..a82739cf Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ContainmentType.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Contains.class b/core/out/production/classes/eu/mihosoft/vmf/core/Contains.class new file mode 100644 index 00000000..d22aefdf Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Contains.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/DefaultValue.class b/core/out/production/classes/eu/mihosoft/vmf/core/DefaultValue.class new file mode 100644 index 00000000..503bd3be Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/DefaultValue.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/DelegateTo.class b/core/out/production/classes/eu/mihosoft/vmf/core/DelegateTo.class new file mode 100644 index 00000000..745c98a0 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/DelegateTo.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/DelegationInfo.class b/core/out/production/classes/eu/mihosoft/vmf/core/DelegationInfo.class new file mode 100644 index 00000000..1905d958 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/DelegationInfo.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Doc.class b/core/out/production/classes/eu/mihosoft/vmf/core/Doc.class new file mode 100644 index 00000000..349cd58b Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Doc.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/GetterOnly.class b/core/out/production/classes/eu/mihosoft/vmf/core/GetterOnly.class new file mode 100644 index 00000000..78d6744e Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/GetterOnly.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/IgnoreEquals.class b/core/out/production/classes/eu/mihosoft/vmf/core/IgnoreEquals.class new file mode 100644 index 00000000..57c7be87 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/IgnoreEquals.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/IgnoreToString.class b/core/out/production/classes/eu/mihosoft/vmf/core/IgnoreToString.class new file mode 100644 index 00000000..b7767afd Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/IgnoreToString.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Immutable.class b/core/out/production/classes/eu/mihosoft/vmf/core/Immutable.class new file mode 100644 index 00000000..7016c291 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Immutable.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Implementation.class b/core/out/production/classes/eu/mihosoft/vmf/core/Implementation.class new file mode 100644 index 00000000..8e8f45aa Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Implementation.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Interface.class b/core/out/production/classes/eu/mihosoft/vmf/core/Interface.class new file mode 100644 index 00000000..3d57e6dd Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Interface.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/InterfaceOnly.class b/core/out/production/classes/eu/mihosoft/vmf/core/InterfaceOnly.class new file mode 100644 index 00000000..a01a163f Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/InterfaceOnly.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Model.class b/core/out/production/classes/eu/mihosoft/vmf/core/Model.class new file mode 100644 index 00000000..77ed62f3 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Model.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ModelConfig.class b/core/out/production/classes/eu/mihosoft/vmf/core/ModelConfig.class new file mode 100644 index 00000000..7c883548 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ModelConfig.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ModelType$1.class b/core/out/production/classes/eu/mihosoft/vmf/core/ModelType$1.class new file mode 100644 index 00000000..00e9f5f5 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ModelType$1.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ModelType.class b/core/out/production/classes/eu/mihosoft/vmf/core/ModelType.class new file mode 100644 index 00000000..da066bf6 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ModelType.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ObservableObject.class b/core/out/production/classes/eu/mihosoft/vmf/core/ObservableObject.class new file mode 100644 index 00000000..8167701a Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ObservableObject.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Prop.class b/core/out/production/classes/eu/mihosoft/vmf/core/Prop.class new file mode 100644 index 00000000..c76986d6 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Prop.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/PropType.class b/core/out/production/classes/eu/mihosoft/vmf/core/PropType.class new file mode 100644 index 00000000..1580bf69 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/PropType.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/PropertyOrder.class b/core/out/production/classes/eu/mihosoft/vmf/core/PropertyOrder.class new file mode 100644 index 00000000..db13f9c9 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/PropertyOrder.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ReadOnlyImplementation.class b/core/out/production/classes/eu/mihosoft/vmf/core/ReadOnlyImplementation.class new file mode 100644 index 00000000..68bc4127 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ReadOnlyImplementation.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ReadOnlyInterface.class b/core/out/production/classes/eu/mihosoft/vmf/core/ReadOnlyInterface.class new file mode 100644 index 00000000..f4a5e495 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ReadOnlyInterface.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/ReferenceInfo.class b/core/out/production/classes/eu/mihosoft/vmf/core/ReferenceInfo.class new file mode 100644 index 00000000..8dbf2020 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/ReferenceInfo.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Refers.class b/core/out/production/classes/eu/mihosoft/vmf/core/Refers.class new file mode 100644 index 00000000..9b0b555d Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Refers.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/Required.class b/core/out/production/classes/eu/mihosoft/vmf/core/Required.class new file mode 100644 index 00000000..c2ae13bc Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/Required.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/StringUtil.class b/core/out/production/classes/eu/mihosoft/vmf/core/StringUtil.class new file mode 100644 index 00000000..14ed9aa2 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/StringUtil.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/SyncInfo.class b/core/out/production/classes/eu/mihosoft/vmf/core/SyncInfo.class new file mode 100644 index 00000000..3aa2733a Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/SyncInfo.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/SyncWith.class b/core/out/production/classes/eu/mihosoft/vmf/core/SyncWith.class new file mode 100644 index 00000000..0b9df548 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/SyncWith.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/TypeUtil.class b/core/out/production/classes/eu/mihosoft/vmf/core/TypeUtil.class new file mode 100644 index 00000000..f19813f8 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/TypeUtil.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/VMFDefaultLogger.class b/core/out/production/classes/eu/mihosoft/vmf/core/VMFDefaultLogger.class new file mode 100644 index 00000000..8bfb15bf Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/VMFDefaultLogger.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/VMFEngineProperties.class b/core/out/production/classes/eu/mihosoft/vmf/core/VMFEngineProperties.class new file mode 100644 index 00000000..f22dbb23 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/VMFEngineProperties.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/VMFEquals$EqualsType.class b/core/out/production/classes/eu/mihosoft/vmf/core/VMFEquals$EqualsType.class new file mode 100644 index 00000000..c88a1a20 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/VMFEquals$EqualsType.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/VMFEquals.class b/core/out/production/classes/eu/mihosoft/vmf/core/VMFEquals.class new file mode 100644 index 00000000..909a378c Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/VMFEquals.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/VMFModel.class b/core/out/production/classes/eu/mihosoft/vmf/core/VMFModel.class new file mode 100644 index 00000000..b7b70358 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/VMFModel.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/VMFResourceLoader.class b/core/out/production/classes/eu/mihosoft/vmf/core/VMFResourceLoader.class new file mode 100644 index 00000000..e5f2cfd8 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/VMFResourceLoader.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/io/FileResource.class b/core/out/production/classes/eu/mihosoft/vmf/core/io/FileResource.class new file mode 100644 index 00000000..3cfdcc70 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/io/FileResource.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/io/FileResourceSet.class b/core/out/production/classes/eu/mihosoft/vmf/core/io/FileResourceSet.class new file mode 100644 index 00000000..63f0c15b Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/io/FileResourceSet.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/io/MemoryResource.class b/core/out/production/classes/eu/mihosoft/vmf/core/io/MemoryResource.class new file mode 100644 index 00000000..45ae0574 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/io/MemoryResource.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/io/MemoryResourceSet.class b/core/out/production/classes/eu/mihosoft/vmf/core/io/MemoryResourceSet.class new file mode 100644 index 00000000..5ebf3811 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/io/MemoryResourceSet.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/io/Resource.class b/core/out/production/classes/eu/mihosoft/vmf/core/io/Resource.class new file mode 100644 index 00000000..ef150e87 Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/io/Resource.class differ diff --git a/core/out/production/classes/eu/mihosoft/vmf/core/io/ResourceSet.class b/core/out/production/classes/eu/mihosoft/vmf/core/io/ResourceSet.class new file mode 100644 index 00000000..992eb72a Binary files /dev/null and b/core/out/production/classes/eu/mihosoft/vmf/core/io/ResourceSet.class differ diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/immutable-implementation.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/immutable-implementation.vm new file mode 100644 index 00000000..9ebcd1fe --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/immutable-implementation.vm @@ -0,0 +1,273 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${type.implementation.packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal.*; +//import ${VCOLL_PKG}.*; +import ${type.packageName}.*; +//import java.beans.PropertyChangeSupport; +//import java.beans.PropertyChangeListener; +//import java.util.Objects; +//import java.util.Arrays; + +// property types imports +#foreach( $import in $type.implementation.imports ) +import $import; +#end + +// implementation + +/** + * An implementation of the immutable model object {@code $type.fullTypeName}. + */ +@SuppressWarnings("deprecation") +public class $type.implementation.typeName implements $type.typeName, ${VMFPKG}.VObject, ${VMFPKG_INT}.VObjectInternal, VCloneableInternal { + + // -------------------------------------------------------------------- + // --- declaration of member variables + // -------------------------------------------------------------------- + +#parse("${VMF_TEMPLATE_PATH}impl/declare-props.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/declare-delegates.vm") + + // referenced by + private final ${VCOLL_PKG}.VList<${VMFPKG}.VObject> referencedBy = ${VCOLL_PKG}.VList.newInstance(new java.util.ArrayList<>()); + // references + private final ${VCOLL_PKG}.VList<${VMFPKG}.VObject> references = ${VCOLL_PKG}.VList.newInstance(new java.util.ArrayList<>()); + + // -------------------------------------------------------------------- + // --- private constructor + // -------------------------------------------------------------------- + + private ${type.implementation.typeName}() { + // ... + } + + // -------------------------------------------------------------------- + // --- public getter methods for accessing properties + // -------------------------------------------------------------------- + +##parse("${VMF_TEMPLATE_PATH}impl/getter.vm") +#foreach( $prop in ${type.implementation.properties} ) + @Override + public $prop.getterDeclaration { + #if($prop.propType == "COLLECTION") + if(this.__vmf_prop_$prop.name==null) { + this.__vmf_prop_${prop.name} = ${VCOLL_PKG}.VList.newInstance( + java.util.Collections.emptyList(); + ); + } + #else## if is collection type + return this.__vmf_prop_${prop.name}; + #end## if is collection type + } +#end##foreach property + + // -------------------------------------------------------------------- + // --- Object methods (equals(), toString() etc.) + // -------------------------------------------------------------------- + +#parse("${VMF_TEMPLATE_PATH}impl/to-string.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/equals.vm") + + public $type.typeName clone() { + // we don't need to perform actual cloning since this is an + // immutable type + return this; + } + +#parse("${VMF_TEMPLATE_PATH}impl/builder.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/delegation-methods.vm") + + // -------------------------------------------------------------------- + // --- Utility methods + // -------------------------------------------------------------------- + + @Override + public void addPropertyChangeListener(java.beans.PropertyChangeListener l) { + // don't do anything. immutable types don't publish change events + } + @Override + public void removePropertyChangeListener(java.beans.PropertyChangeListener l) { + // don't do anything. immutable types don't publish change events + } + + private boolean _vmf_hasListeners() { + return false; + } + + /*package private*/ void _vmf_firePropertyChangeIfListenersArePresent() { + // don't do anything. immutable types don't publish change events + } + + @Override + public ${type.typeName} _vmf_deepCopy( + java.util.IdentityHashMap identityMap) { + return this; + } + + @Override + public ${type.typeName} _vmf_shallowCopy( + java.util.IdentityHashMap identityMap) { + return this; + } + + // -------------------------------------------------------------------- + // --- Public VMF API + // -------------------------------------------------------------------- + + private ${VMFPKG}.VMF vmf; + + @Override + public ${VMFPKG}.VMF vmf() { + if(vmf==null) { + vmf = new ${VMFPKG}.VMF() { + public ${VMFPKG}.Content content() { + return new ${VMFPKG}.Content() { + public ${VMFPKG}.VIterator iterator() { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this); + } + public java.util.stream.Stream<${VMFPKG}.VObject> stream() { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this).asStream(); + } + + public ${VMFPKG}.VIterator iterator(${VMFPKG}.VIterator.IterationStrategy strategy) { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this, strategy); + } + public java.util.stream.Stream<${VMFPKG}.VObject> stream(${VMFPKG}.VIterator.IterationStrategy strategy) { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this, strategy).asStream(); + } + public java.util.stream.Stream stream(Class type) { + return stream().filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e); + } + public java.util.stream.Stream stream(Class type, ${VMFPKG}.VIterator.IterationStrategy strategy) { + return stream(strategy).filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e); + } + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> referencedBy() { + return _vmf_referencedBy().asUnmodifiable(); + } + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> references() { + return _vmf_references().asUnmodifiable(); + } + + @Override + public ${type.typeName} deepCopy() { + java.util.IdentityHashMap identityMap = + new java.util.IdentityHashMap<>(); + return _vmf_deepCopy(identityMap); + } + + @Override + public ${type.typeName} shallowCopy() { + // we don't copy anything since this is an immutable type + return ${type.implementation.typeName}.this; + } + }; + } + + private ${VMFPKG_INT}.ChangesImpl changes; + + public ${VMFPKG}.Changes changes() { + if (changes==null) { + changes = new ${VMFPKG_INT}.ChangesImpl(); + changes.setModel(${type.implementation.typeName}.this); + } + + return changes; + } + + private ${VMFPKG_INT}.ReflectImpl reflect; + + public ${VMFPKG}.Reflect reflect() { + if (reflect==null) { + reflect = new ${VMFPKG_INT}.ReflectImpl(); + reflect.setModel(${type.implementation.typeName}.this); + } + + return reflect; + } + + }; // end vmf + } // end if null + + return vmf; + } + + @Override + public ${type.typeName} asReadOnly() { + return this; + } + + // Type info + @Override + public ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type _vmf_getType() { + return ${type.packageName}.${type.typeName}.type(); + } + + // -------------------------------------------------------------------- + // --- Reflection methods + // -------------------------------------------------------------------- + + // type id for improved reflection performance + public static final int _VMF_TYPE_ID = $type.typeId; + + @Override + public int _vmf_getTypeId() { + return _VMF_TYPE_ID; + } + +#set($readOnlyVal=true) +#parse("${VMF_TEMPLATE_PATH}reflection/reflection.vm") + + // -------------------------------------------------------------------- + // --- Id related methods + // -------------------------------------------------------------------- + + // id management is currently not part of VMF (TODO how should we support this?) + + // -------------------------------------------------------------------- + // --- Reference methods + // -------------------------------------------------------------------- + + @Override + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> _vmf_referencedBy() { + // TODO 17.02.2019 feature deactivated due to huge memory consumption + // return this.referencedBy; + throw new UnsupportedOperationException("TODO 17.02.2019 feature deactivated due to huge memory consumption"); + } + @Override + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> _vmf_references() { + // TODO 17.02.2019 feature deactivated due to huge memory consumption + // return this.references; + throw new UnsupportedOperationException("TODO 17.02.2019 feature deactivated due to huge memory consumption"); + } + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/immutable-interface.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/immutable-interface.vm new file mode 100644 index 00000000..71a4d5f9 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/immutable-interface.vm @@ -0,0 +1,127 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${type.packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +//import ${VCOLL_PKG}.*; + +// property types imports +#foreach( $import in $type.imports ) +import $import; +#end + +// interface + +/** + *#if($type.interfaceOnly) An interface-only#else A#end representation of the immutable model object {@code $type.fullTypeName}. + * + * +#if(${type.documented}) + *

${type.customDocumentation}

+#else + * + * +#end + * + * + */ +public interface $type.typeName extends ${VMFPKG}.VObject$type.immutableImplementsString, Cloneable, ${VMFPKG}.Immutable { +#foreach( $prop in ${type.interface.properties} ) + +#parse("${VMF_TEMPLATE_PATH}interface/getter.vm") + +#end ## for each + +#if(!$type.interfaceOnly) + + /** + * Returns the Type object of this model type. + * @return Type object + */ + static ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type type() { + return __VMF__${type.typeName}_Creator.getType(); + } + +#parse("${VMF_TEMPLATE_PATH}interface/builder.vm") +#end##if type interface only + + /** + * Returns a read-only wrapper of '{@link ${type.typeName} ${type.typeName}}'. Since this model object is immutable + this method does not perform any conversion and returns this object in unmodified form. + * @return a read-only wrapper of '{@link ${type.typeName} ${type.typeName}}' + */ + ${type.typeName} asReadOnly(); + + /** + * Returns a deep clone of this object. + * @return a deep clone of this object + */ + @Override + $type.typeName clone() /*throws CloneNotSupportedException*/; + +} + +#if(!$type.interfaceOnly) +class __VMF__${type.typeName}_Creator { + + static Class builderCls; + static java.lang.invoke.MethodHandles.Lookup lookup; + static java.lang.reflect.Constructor builderConstructor; + static java.lang.invoke.MethodHandle builderConstructorMH; + + static ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type type; + + static ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type getType() { + if(type ==null) { + type = ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type.newInstance(true, false, "${type.packageName}.$type.typeName", ${type.packageName}.${type.typeName}.class); + } + return type; + } + + static ${type.typeName}.Builder newBuilderInstance() { + try {#set ( $dollar_sign = "$") + + if(builderCls==null) { + builderCls = Class.forName("${type.implementation.packageName}.${type.implementation.typeName}${dollar_sign}Builder${VMF_IMPL_CLASS_EXT}"); + + if(lookup==null) { lookup = java.lang.invoke.MethodHandles.lookup(); } + + builderConstructor = builderCls.getConstructor(); + builderConstructor.setAccessible(true); + + builderConstructorMH = lookup.unreflectConstructor(builderConstructor); + } + + return (${type.typeName}.Builder) builderConstructorMH.invoke(); + + } catch (Throwable tr) { + throw new RuntimeException("Cannot instantiate \"${type.implementation.packageName}.${type.implementation.typeName}\"", tr); + } + } +} + +#end##if type interface only diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/builder.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/builder.vm new file mode 100644 index 00000000..3f5b05fd --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/builder.vm @@ -0,0 +1,156 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +// -------------------------------------------------------------------- +// --- Builder methods +// -------------------------------------------------------------------- + +public static class Builder${VMF_IMPL_CLASS_EXT} implements ${type.typeName}.Builder { + +#foreach( $prop in ${type.implementation.properties}) +###if($type.immutable || $prop.propType != "COLLECTION") + private $prop.typeName __vmf_prop_$prop.name; +###end## if type is immutable or property is no collection +#end + + private boolean appendCollections = true; + + public Builder${VMF_IMPL_CLASS_EXT}() { + // -------------------------------------------------------------------- + // --- initialization of default values + // -------------------------------------------------------------------- + #foreach($prop in $type.implementation.properties) + // property ${foreach.index} + #if(${prop.getDefaultValueAsString()}!="null") + __vmf_prop_$prop.name = ${prop.getDefaultValueAsString()}; + #else##if default is present + // -> no default value is present + #end## if default is present + #end## for-each property + } + +#foreach( $prop in ${type.implementation.properties} ) +#if(!$prop.containmentProperty || ${prop.containmentInfo.containmentType}!="CONTAINER") +#if($prop.propType == "COLLECTION") + public ${type.typeName}.Builder with${prop.nameWithUpperCase}(java.util.List<${prop.genericPackageName}.${prop.genericTypeName}> ${prop.name}) { + // ensure that this collection property is really immutable + this.__vmf_prop_${prop.name} = ${VCOLL_PKG}.VList.newInstance( + java.util.Collections. + unmodifiableList( +#if(${prop.genericType}) + new java.util.ArrayList<${prop.genericType.typeName}>(${prop.name}) +#else## if genericType is modelType + new java.util.ArrayList<${prop.genericPackageName}.${prop.genericTypeName}>(${prop.name}) +#end## if genericType is modelType + ) + ); + return this; + } + public Builder with${prop.nameWithUpperCase}(${prop.genericPackageName}.${prop.genericTypeName}... ${prop.name}) { + return with${prop.nameWithUpperCase}(java.util.Arrays.asList(${prop.name})); + } +#else## if property is collection + public ${type.typeName}.Builder with${prop.nameWithUpperCase}(${prop.typeName} ${prop.name}) { + this.__vmf_prop_${prop.name} = ${prop.name}; + return this; + } +#end## if property is collection +#end## if type is no container or property is no containment type +#end## foreach property + public Builder appendCollections(boolean value) { + this.appendCollections = value; + return this; + } + + public $type.typeName build() { + ${type.implementation.typeName} result = new ${type.implementation.typeName}(); +#foreach( $prop in ${type.implementation.properties} ) +#if($type.immutable || $prop.propType != "COLLECTION") + result.__vmf_prop_${prop.name} = this.__vmf_prop_${prop.name}; +#if($prop.type) + // PROP: $prop.name + #set($objectToAddReferenceOnValue="result") + #set($referenceToAddValue = "result.__vmf_prop_"+${prop.name}) + #set($objectToRemoveReferenceOnValue = false) + #set($referenceToRemoveValue = false) + #set($codeIndentValue = " ") + #parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") +#end## if property is model-type +#end## if type is immutable or property is no collection +#if($prop.propType == "COLLECTION") + if(this.__vmf_prop_${prop.name} !=null) { + result.get${prop.nameWithUpperCase}().addAll(this.__vmf_prop_${prop.name}); + } +#end +#end## foreach property + return result; + } + + public Builder applyFrom(${type.typeName} o) { +#foreach( $prop in ${type.implementation.properties} ) +###if($type.immutable || $prop.propType != "COLLECTION") +#if($prop.propType == "COLLECTION") +#if(${prop.genericType}) +#set($genericCollArg = "${prop.genericType.typeName}") +#else## if genericType is modelType +#set($genericCollArg = "${prop.genericPackageName}.${prop.genericTypeName}") +#end## if genericType is modelType + if(!this.appendCollections||this.__vmf_prop_${prop.name}==null) { + // ensure that this collection property is really immutable + this.__vmf_prop_${prop.name} = ${VCOLL_PKG}.VList.newInstance( + java.util.Collections. + unmodifiableList( + new java.util.ArrayList<$genericCollArg>(o.${prop.getterPrefix}${prop.nameWithUpperCase}()) + ) + ); + } else { + this.__vmf_prop_${prop.name}.addAll(o.${prop.getterPrefix}${prop.nameWithUpperCase}()); + } +#else## if property is collection + this.__vmf_prop_${prop.name} = o.${prop.getterPrefix}${prop.nameWithUpperCase}(); +#end## if property is collection +###end## if type is immutable or property is no collection +#end## foreach property + + return this; + } +#if(!$type.immutable) + public Builder applyTo(${type.typeName} o) { + +#foreach( $prop in ${type.implementation.properties} ) +#if($prop.propType == "COLLECTION") + if(!this.appendCollections) { + o.${prop.getterPrefix}${prop.nameWithUpperCase}().clear(); + } + o.${prop.getterPrefix}${prop.nameWithUpperCase}().addAll(this.__vmf_prop_${prop.name}); +#else## if property is collection +#if(!$prop.containmentProperty) + o.set${prop.nameWithUpperCase}(this.__vmf_prop_${prop.name}); +#end## if property is not containment property +#end## if property is collection +#end## foreach property + + return this; + } +#end## if type is not immutable +} // end class Builder${VMF_IMPL_CLASS_EXT} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/clone.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/clone.vm new file mode 100644 index 00000000..3d0d93af --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/clone.vm @@ -0,0 +1,123 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# + // --------------------------- BEGIN CLONING ----------------------------- + /** + * Package private copy constructor. + * It creates a deep or shallow copy of the specified other object. + * @param other other object + * @param deepCopy defines whether to perform a deep copy + */ + ${type.implementation.typeName} ( + ${type.implementation.typeName} other, + boolean deepCopy, java.util.IdentityHashMap identityMap + ) { + identityMap.put(other,this); + +#foreach ($prop in $type.implementation.properties) +#if(!$prop.container) +#if($prop.propType=="COLLECTION") + if(deepCopy) { + if(other.__vmf_prop_${prop.name}!=null) { +#if($prop.genericType) + // element type is a model type + for($prop.genericType.typeName e : other.__vmf_prop_${prop.name}) { + // TODO do a bulk operation instead + ${VMFPKG_INT}.VObjectInternal eClone = (${VMFPKG_INT}.VObjectInternal)($prop.genericType.typeName)((VCloneableInternal)e)._vmf_deepCopy(identityMap); + this.get${prop.nameWithUpperCase}().add(($prop.genericType.typeName)eClone); + } +#else ## if prop genericType + // element type is an external type (TODO implement cloning strategy) + this.get${prop.nameWithUpperCase}().addAll(other.__vmf_prop_${prop.name}); +#end ## if prop genericType + } else { + // nothing to copy + } + } else { + this.__vmf_prop_$prop.name = other.__vmf_prop_$prop.name; + } +#if($prop.contained) + if(this.__vmf_prop_${prop.name}!=null && !deepCopy) { + throw new RuntimeException("Cannot create shallow copy of containment properties. Use 'deepCopy()' instead."); +## this.__vmf_prop_${prop.name}.forEach((e) -> { +## #set($propertyToModifyValue = "e") +## #set($oppositeValue = "this") +## #set($codeIndentValue = " ") +## #parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") +## }); + } +#end ## if contained +#else ## if collection +#if($prop.type) + // property type is a model type + if(deepCopy) { + if(other.__vmf_prop_${prop.name}!=null) { + this.set${prop.nameWithUpperCase}(($prop.typeName)((VCloneableInternal)other.__vmf_prop_${prop.name})._vmf_deepCopy(identityMap)); + } + } else { + this.__vmf_prop_$prop.name = other.__vmf_prop_$prop.name; + } +#else ## if prop type + // property type is an external type (TODO implement cloning strategy) + this.set${prop.nameWithUpperCase}(other.__vmf_prop_${prop.name}); +#end ## if prop type +#end ## if collection +#end ## if container type +#end ## for-each property + + } // end copy constructor + + @Override + public ${type.implementation.typeName} _vmf_deepCopy(java.util.IdentityHashMap identityMap) { + if(identityMap.containsKey(this)) { + return (${type.implementation.typeName})identityMap.get(this); + } else { + ${type.implementation.typeName} clonedVal = new ${type.implementation.typeName}(this, true, identityMap); + return clonedVal; + } + } + + @Override + public ${type.implementation.typeName} _vmf_shallowCopy(java.util.IdentityHashMap identityMap) { + if(identityMap.containsKey(this)) { + return (${type.implementation.typeName})identityMap.get(this); + } else { + ${type.implementation.typeName} clonedVal = new ${type.implementation.typeName}(this, false, identityMap); + return clonedVal; + } + } +#if(${type.isCloneMethodDelegated()}) + // -> clone() method is delegated +#else## #if(${type.isCloneMethodDelegated()}) + @Override + public ${type.implementation.typeName} clone() /*throws CloneNotSupportedException*/ { + // http://stackoverflow.com/questions/12886036/deep-copying-a-graph-structure + // http://softwareengineering.stackexchange.com/questions/228848/how-does-java-handle-cyclic-data-references-when-serializing-an-object + // https://gist.github.com/kanrourou/47223bdaf481505d4c7e + // http://www.programcreek.com/2012/12/leetcode-clone-graph-java/ + java.util.IdentityHashMap identityMap = + new java.util.IdentityHashMap<>(); + return _vmf_deepCopy(identityMap); + } +#end## #if(${type.isCloneMethodDelegated()}) + // ---------------------------- END CLONING ------------------------------ \ No newline at end of file diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/constructor-delegates.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/constructor-delegates.vm new file mode 100644 index 00000000..753e5679 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/constructor-delegates.vm @@ -0,0 +1,37 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +// -------------------------------------------------------------------- +// --- declaration of constructor delegation methods +// -------------------------------------------------------------------- + +#foreach( $delegate in ${type.implementation.constructorDelegations}) + + if($delegate.varName==null) { + $delegate.varName = new ${delegate.fullTypeName}(); + ${delegate.varName}.setCaller(this); + } + + $delegate.varName.${delegate.methodName}(); + +#end## for each delegate diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/declare-delegates.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/declare-delegates.vm new file mode 100644 index 00000000..16a961da --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/declare-delegates.vm @@ -0,0 +1,30 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +// -------------------------------------------------------------------- +// --- declaration of delegation variables +// -------------------------------------------------------------------- + +#foreach( $delegate in ${type.implementation.delegationsOneForEachType}) + private $delegate.fullTypeName $delegate.varName; +#end diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/declare-props.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/declare-props.vm new file mode 100644 index 00000000..c61b99ef --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/declare-props.vm @@ -0,0 +1,58 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +#if(${type.containedWithoutOpposite}) + // containment prop (for containments without specified opposite) + /*package private*/ ${VMFPKG}.VObject __vmf_internal_container; + @Override public ${VMFPKG}.VObject _vmf_getContainer() {return this.__vmf_internal_container;} + @Override public void _vmf_setContainer(${VMFPKG}.VObject container) {this.__vmf_internal_container = container;} +#end + +#foreach( $prop in ${type.implementation.properties}) + // --- PROP '$prop.typeName' + /*package private*/ $prop.typeName __vmf_prop_$prop.name; +#if(${prop.crossRefProperty} && ${prop.propType} == "COLLECTION") + /*package private*/ java.util.List<${prop.genericTypeName}> __vmf_prop_${prop.name}__vmf_RawList; +#end## cross-ref collection +#if(!$type.immutable) +#if(${prop.isInheritedProp()})## if inheritedprop + // -> prop is inherited from: '${prop.inheritedProp.parent.typeName}.${prop.inheritedProp.name}' + // -> we have to stick to the parent method signature and do the necessary casting in the setter impl, see (*1*) + @Override public void __vmf_set_prop_${prop.name}(${prop.inheritedProp.typeName} obj) {this.__vmf_prop_${prop.name} = /* (*1*) */($prop.typeName)obj;} +#else##------------------------- else inheritedprop + @Override public void __vmf_set_prop_${prop.name}($prop.typeName obj) {this.__vmf_prop_${prop.name} = obj;} +#end##-------------------------- end inheritedprop + //@Override public void __vmf_set_prop_${prop.name}($prop.typeName obj) {this.__vmf_prop_${prop.name} = obj;} + @Override public $prop.typeName __vmf_get_prop_${prop.name}() {return this.__vmf_prop_${prop.name};} +#if(${prop.crossRefProperty} && ${prop.propType} == "COLLECTION") + @Override public java.util.List<${prop.genericTypeName}> __vmf_get_prop_${prop.name}__vmf_RawList() { + + if(this.__vmf_prop_${prop.name}__vmf_RawList==null) { + __vmf_prop_${prop.name}__vmf_RawList = new java.util.ArrayList<>(); + } + + return this.__vmf_prop_${prop.name}__vmf_RawList; + }; +#end## cross-ref collection +#end## is not immutable +#end diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/delegation-methods.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/delegation-methods.vm new file mode 100644 index 00000000..f2ad968c --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/delegation-methods.vm @@ -0,0 +1,42 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +// -------------------------------------------------------------------- +// --- declaration of delegation methods +// -------------------------------------------------------------------- +## // ALL: ${type.implementation.delegations.size()} +## // METHODS: ${type.implementation.methodDelegations.size()} +## // CONSTRUCTOR: ${type.implementation.constructorDelegations.size()} +## // ONE_FOR_EACH_TYPE: ${type.implementation.delegationsOneForEachType.size()} +#foreach( $delegate in ${type.implementation.methodDelegations}) + $delegate.methodDeclaration { + + if($delegate.varName==null) { + $delegate.varName = new ${delegate.fullTypeName}(); + ${delegate.varName}.setCaller(this); + } + + #if(!${delegate.isVoid()})return#end $delegate.varName.${delegate.methodName}(#foreach($p in ${delegate.paramNames})$p#if($foreach.hasNext), #end#end); + } + +#end## for each delegate diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/equals.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/equals.vm new file mode 100644 index 00000000..add3b43a --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/equals.vm @@ -0,0 +1,278 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# + // --------------------------- BEGIN EQUALITY ----------------------------- + + @Override + public boolean _vmf_equals(Object o) { + + boolean entry = _vmf_getThreadLocalEquals().get().isEmpty(); + try { + // test if the object pair (this,o) has been checked before + boolean isImmutable = (o instanceof eu.mihosoft.vmf.runtime.core.Immutable); + if (!isImmutable && _vmf_getThreadLocalEquals().get().containsKey(new ${VMFPKG_INT}.VObjectInternal.EqualsPair(this, o))) { + // This pair has been seen before. That's why we return true now. + // If this pair wasn't equal, we wouldn't need to do a second + // comparison. Returning 'true' is equivalent to ignoring this + // particular test in the calling 'equals()' method. + return true; + } else { + if(!isImmutable) { + _vmf_getThreadLocalEquals().get().put(new ${VMFPKG_INT}.VObjectInternal.EqualsPair(this, o), null); + } + entry = true; + } + + if (o==null) return false; + else if (this==o) return true; + +#if(!$type.immutable) + // if object is read-only wrapper then unwrap the actual object + if(o instanceof $type.readOnlyImplementation.typeName) { + o = (($type.readOnlyImplementation.typeName)o)._vmf_getMutableObject(); + } +#end## if type is not immutable + + // -- try our interface/implementation -- + + // perform the actual comparison for each property + if (o.getClass() == ${type.implementation.typeName}.class) { + $type.implementation.typeName other = ($type.implementation.typeName) o; + +## // DEBUG begin ------------------ +## #foreach ($prop in $type.implementation.propertiesForEquals) +## boolean _v_eq_$prop.name = _vmf_equals_helper(_vmf_getThreadLocalEquals(), this.__vmf_prop_$prop.name, other.__vmf_prop_$prop.name); +## System.out.println("PROP-EQ: ${type.implementation.typeName}.${prop.name} = " + _v_eq_$prop.name + " : " + this.__vmf_prop_$prop.name + ", other: " + other.__vmf_prop_$prop.name); +## #end## for-each property +## // DEBUG end -------------------- + + return #if($type.implementation.propertiesForEquals.isEmpty())true;#end +#foreach ($prop in $type.implementation.propertiesForEquals) + _vmf_equals_helper(_vmf_getThreadLocalEquals(), this.__vmf_prop_$prop.name, other.__vmf_prop_$prop.name)#if($foreach.hasNext) &&#else;#end + +#end## for-each property + } + +// TODO 16.10.2019 should we allow mixed-type comparison? How should it be implemented? +## +## // -- try every implementation that implements our interface -- +## #foreach ($t in $type.getModel().getAllTypesThatImplement($type)) +## #if($t.interfaceOnly) +## +## // -> type ${t.typeName} is interface-only and will be skipped +## +## #else## if($t.interfaceOnly) +## +## // -> type ${t.typeName} is checked: +## +## // -> perform the actual comparison for each property +## if (o instanceof ${t.implementation.typeName}) { +## $t.implementation.typeName other = ($t.implementation.typeName) o; +## return #if($t.implementation.propertiesForEquals.isEmpty())true;#end +## +## #foreach ($prop in $type.implementation.propertiesForEquals) +## // $prop.name : $prop.container : $prop.contained +## _vmf_equals_helper(_vmf_getThreadLocalEquals(), this.__vmf_prop_$prop.name, other.__vmf_prop_$prop.name)#if($foreach.hasNext) &&#else;#end +## +## #end## for-each property +## } +## #end## if($t.interfaceOnly) +## #end## for-each potential implementation + + // no implementation matched. we end the comparison. + return false; + } finally { + if (entry) { + _vmf_getThreadLocalEquals().get().clear(); + _vmf_fEqualsChecker = null; + } + } + } // end equals() + + private static boolean _vmf_equals_helper(ThreadLocal> threadLocalEqualsMap, Object o1, Object o2) { + boolean oneAndOnlyOneIsNull = (o1 == null) != (o2 == null); + boolean o1IsCollectionType = o1 instanceof ${VCOLL_PKG}.VList; + boolean o2IsCollectionType = o2 instanceof ${VCOLL_PKG}.VList; + + // if only one is a collection we are not equal + // (we can only know for sure if both are not null, see below) + if( (o1IsCollectionType!=o2IsCollectionType) && (o1!=null && o2!=null) ) return false; + + // we assume collection type if either + // - both are collection type or + // - if one is null and the other is a collection object + // (to ensure we are able to compare lazy init, i.e.: [] == null) + boolean collectionType = (o1IsCollectionType && o2IsCollectionType) + || ( (o1IsCollectionType || o2IsCollectionType) && oneAndOnlyOneIsNull ); + + // since we support lazy initialization for collections, + // uninitialized empty collection values are defined as equal to null + // otherwise we would have to initialize these values, which would then + // neutralize or even negate the positive effect of lazy initialization + if(oneAndOnlyOneIsNull && collectionType) { + if(o1==null) { + return ((${VCOLL_PKG}.VList)o2).isEmpty(); + } else { + return ((${VCOLL_PKG}.VList)o1).isEmpty(); + } + } else { + + // if o1 is a model type reuse the threadLocalEqualsMap + if(o1 instanceof ${VMFPKG_INT}.VObjectInternal) { + ${VMFPKG_INT}.VObjectInternal vObj1 = (${VMFPKG_INT}.VObjectInternal)o1; + vObj1._vmf_setThreadLocalEquals(threadLocalEqualsMap); + } + + if(o2 instanceof ${VMFPKG_INT}.VObjectInternal) { + ${VMFPKG_INT}.VObjectInternal vObj2 = (${VMFPKG_INT}.VObjectInternal)o2; + vObj2._vmf_setThreadLocalEquals(threadLocalEqualsMap); + } + + if(o1IsCollectionType) { + ${VCOLL_PKG}.VList l1 = (${VCOLL_PKG}.VList)o1; + + l1.stream().filter(entry->entry instanceof ${VMFPKG_INT}.VObjectInternal). + forEach(entry->{ + ${VMFPKG_INT}.VObjectInternal vObjInt = (${VMFPKG_INT}.VObjectInternal)entry; + vObjInt._vmf_setThreadLocalEquals(threadLocalEqualsMap); + }); + } + if(o2IsCollectionType) { + ${VCOLL_PKG}.VList l2 = (${VCOLL_PKG}.VList)o2; + + l2.stream().filter(entry->entry instanceof ${VMFPKG_INT}.VObjectInternal). + forEach(entry->{ + ${VMFPKG_INT}.VObjectInternal vObjInt = (${VMFPKG_INT}.VObjectInternal)entry; + vObjInt._vmf_setThreadLocalEquals(threadLocalEqualsMap); + }); + } + + boolean bothAreVObjects = o1 instanceof ${VMFPKG_INT}.VObjectInternal && o2 instanceof ${VMFPKG_INT}.VObjectInternal; + boolean useVMFEquals = false; + + if(bothAreVObjects) { + ${VMFPKG_INT}.VObjectInternal vo1 = (${VMFPKG_INT}.VObjectInternal)o1; + ${VMFPKG_INT}.VObjectInternal vo2 = (${VMFPKG_INT}.VObjectInternal)o2; + useVMFEquals = true;//vo1._vmf_use_vmf_equals() && vo2._vmf_use_vmf_equals(); + } + + if(useVMFEquals) { + return ((${VMFPKG_INT}.VObjectInternal)o1)._vmf_equals(o2); + } else { + return java.util.Objects.equals(o1,o2); + } + } + } + + @Override + public int _vmf_hashCode() { + + boolean entry = _vmf_getThreadLocalHashCode().get().isEmpty(); + try { + // test if "this class" has been seen before + // + // WARNING we use `System.identityHashCode(this)` to prevent recursive + // hashCode() calls before we do the actual test. This would eliminate + // the effect of the thread-local map + if (_vmf_getThreadLocalHashCode().get().containsKey(System.identityHashCode(this))) { + return 0; // already visited + } else { + _vmf_getThreadLocalHashCode().get().put(System.identityHashCode(this), null); + int value = +#if(${type.isEqualsAndHashCodeCallSuper()})super.hashCode() + #end + _vmf_deepHashCode( +#foreach ($prop in $type.implementation.propertiesForEquals) + this.__vmf_prop_$prop.name#if($foreach.hasNext),#end +#end ); + entry = true; + return value; + } + + } finally { + if (entry) { + _vmf_getThreadLocalHashCode().get().clear(); + _vmf_fHashCodeChecker = null; + } + } + + } // end hashCode() + + // fixes 'array discovery problems' with the 'java.util.Objects.hash(...)' method + // see http://stackoverflow.com/questions/30385018/how-to-use-java-7-objects-hash-with-arrays + private int _vmf_deepHashCode(Object... fields) { + // WARNING we are not allowed to pass arrays that contain itself + // or are contained in nested arrays + return java.util.Arrays.deepHashCode(fields); + } // end _vmf_deepHashCode() + + /*package private*/ ThreadLocal> _vmf_getThreadLocalEquals() { + if (_vmf_fEqualsChecker==null) { + _vmf_fEqualsChecker = ThreadLocal.withInitial( + () -> new java.util.HashMap<>()); + } + + return _vmf_fEqualsChecker; + } + + @Override + public void _vmf_setThreadLocalEquals(ThreadLocal> threadlocalMap) { + _vmf_fEqualsChecker = threadlocalMap; + } + + /*package private*/ ThreadLocal> _vmf_getThreadLocalHashCode() { + if (_vmf_fHashCodeChecker==null) { + _vmf_fHashCodeChecker = ThreadLocal.withInitial( + () -> new java.util.HashMap<>()); + } + + return _vmf_fHashCodeChecker; + } + + private static ThreadLocal> _vmf_fEqualsChecker; + + + private static ThreadLocal> _vmf_fHashCodeChecker; +#if(${type.isEqualsMethodDelegated()}) + // -> equals(Object o) and hashCode() methods are delegated +#elseif(${type.isEqualsAndHashCode()})## #if(${type.isEqualsMethodDelegated()}) + // we use VMF's equals & hashCode implementation + @Override + public boolean equals(Object o) { + return _vmf_equals(o); + } + @Override + public int hashCode() { + return _vmf_hashCode(); + } +#else + // we don't use VMF's equals & hashCode implementation + // @Override + // public boolean equals(Object o) { + // return _vmf_equals(o); + // } + // @Override + // public int hashCode() { + // return _vmf_hashCode(); + // } +#end## #if(${type.isEqualsMethodDelegated()}) + // ---------------------------- END EQUALITY ------------------------------ diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/getter.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/getter.vm new file mode 100644 index 00000000..dfb534cb --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/getter.vm @@ -0,0 +1,324 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +#foreach( $prop in ${type.implementation.properties} ) + +#if(${prop.crossRefProperty} && ${prop.propType} == "COLLECTION") + @Override + public ${prop.getterDeclaration} { + if(this.__vmf_prop_$prop.name==null) { + this.__vmf_prop_$prop.name = ${VCOLL_PKG}.VList.newInstance(__vmf_get_prop_${prop.name}__vmf_RawList()); + +#if(${prop.referenceInfo.opposite.propType} == "COLLECTION" ) + this.__vmf_prop_${prop.name}.addChangeListener( (evt) -> { + + if(${VMFPKG_INT}.ChangeInternal.isCrossRefChange(evt)) { + return; + } + + evt.added().elements().forEach( (e) -> { + if(e==null) return; + +#set($oppositeRefProp=${prop.referenceInfo.opposite}) + + // ${prop.referenceInfo.opposite.propType} + // java.util.List<${oppositeRefProp.genericTypeName}> oppositeRefList = + // ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).__vmf_get_prop_${oppositeRefProp.name}__vmf_RawList(); + // oppositeRefList.add(this); + String eventInfo = ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().getEventInfo(); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().add(this); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(eventInfo); + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "e") +#set($objectToRemoveReferenceOnValue = false) +#set($referenceToRemoveValue = false) +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.added() + + evt.removed().elements().forEach( (e) -> { + if(e==null) return; + +#set($oppositeRefProp=${prop.referenceInfo.opposite}) + // ${prop.referenceInfo.opposite.propType} + // java.util.List<${oppositeRefProp.genericTypeName}> oppositeRefList = + // ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).__vmf_get_prop_${oppositeRefProp.name}__vmf_RawList(); + // oppositeRefList.remove(this); + String eventInfo = ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().getEventInfo(); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().remove(this); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(eventInfo); + +#set($objectToAddReferenceOnValue=false) +#set($referenceToAddValue = false) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "e") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.removed() + }); + +#elseif(${prop.referenceInfo.opposite.propType} != "COLLECTION" ) + this.__vmf_prop_${prop.name}.addChangeListener( (evt) -> { + evt.added().elements().forEach( (e) -> { + if(e==null) return; + + // only look for duplicates if not triggered by cross-ref + if (!java.util.Objects.equals(${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF, this.__vmf_prop_${prop.name}.getEventInfo())) { + // we remove entry e if it is already referenced + // to detect we don't directly count the number of elements (must be < 2) + // but first check whether the new opposite is equal to the previous one + // which indicates that e has been added already + if(this==((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).get${prop.referenceInfo.opposite.nameWithUpperCase}()) { + if(this.__vmf_prop_${prop.name}.stream().filter(el->el==e).count() > 1) this.__vmf_prop_${prop.name}.remove(e); // removed e since it has been already added + // this.__vmf_get_prop_${prop.name}__vmf_RawList().remove(e); // removed e since it has been already added + } + } + +#set($oppositeRefProp=${prop.referenceInfo.opposite}) + // ${prop.referenceInfo.opposite.propType} + Object refOldVal = ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).__vmf_get_prop_${oppositeRefProp.name}(); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).__vmf_set_prop_${oppositeRefProp.name}(this); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e)._vmf_firePropertyChangeIfListenersArePresent("${oppositeRefProp.name}", refOldVal, this, ${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF); + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "e") +#set($objectToRemoveReferenceOnValue = false) +#set($referenceToRemoveValue = false) +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.added() + + evt.removed().elements().forEach( (e) -> { + if(e==null) return; + +#set($oppositeRefProp=${prop.referenceInfo.opposite}) + // ${prop.referenceInfo.opposite.propType} + Object refOldVal = ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).__vmf_get_prop_${oppositeRefProp.name}(); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e).__vmf_set_prop_${oppositeRefProp.name}(null); + ((${prop.parent.packageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)e)._vmf_firePropertyChangeIfListenersArePresent("${oppositeRefProp.name}", refOldVal, null, ${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF); + +#set($objectToAddReferenceOnValue=false) +#set($referenceToAddValue = false) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "e") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.removed() + }); +#end## collection type + + } // end lazy-init + + return this.__vmf_prop_$prop.name; + } +#else## cross-ref prop + @Override + public $prop.getterDeclaration { +#if($prop.containmentProperty && $prop.propType == "COLLECTION" && !${prop.containmentInfo.withoutOpposite}) + + if(this.__vmf_prop_$prop.name==null) { + this.__vmf_prop_$prop.name = ${VCOLL_PKG}.VList.newInstance(new java.util.ArrayList<>()); + + this.__vmf_prop_${prop.name}.addChangeListener( (evt) -> { + evt.added().elements().forEach( (e) -> { + + if(e==null) return; + + // remove element from previous collection + // TODO use bulk operations if possible + if(e.get${prop.containmentInfo.opposite.nameWithUpperCase}()!=null) { + e.get${prop.containmentInfo.opposite.nameWithUpperCase}().get${prop.nameWithUpperCase}().remove(e); + } + +#parse("${VMF_TEMPLATE_PATH}impl/remove-containment-opposites-collection.vm") + + #set($propertyToModifyValue = "e") + #set($oppositeValue = "this") + #set($codeIndentValue = " ") + #set($disableFireEventValue=false) +#parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "e") +#set($objectToRemoveReferenceOnValue = false) +#set($referenceToRemoveValue = false) +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.added() + + evt.removed().elements().forEach( (e) -> { + if(e==null) return; + #set($propertyToModifyValue = "e") + #set($oppositeValue = "null") + #set($codeIndentValue = " ") + #set($disableFireEventValue=false) +#parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + +#set($objectToAddReferenceOnValue=false) +#set($referenceToAddValue = false) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "e") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.removed() + + }); // end of change listener + + } // end of "lazy init" if(this.__vmf_prop_$prop.name==null) + + return this.__vmf_prop_$prop.name; + + // return VContainmentUtil.asContainmentList(this.__vmf_prop_$prop.name, "__vmf_prop_${prop.containmentInfo.opposite.name}"); +#elseif($prop.containmentProperty && $prop.propType == "COLLECTION" && ${prop.containmentInfo.withoutOpposite}) + if(this.__vmf_prop_$prop.name==null) { + this.__vmf_prop_$prop.name = ${VCOLL_PKG}.VList.newInstance(new java.util.ArrayList<>()); + + this.__vmf_prop_${prop.name}.addChangeListener( (evt) -> { + evt.added().elements().forEach( (e) -> { + + if(e==null) return; + +#parse("${VMF_TEMPLATE_PATH}impl/remove-containment-opposites-collection.vm") + +${VMFPKG_INT}.VObjectInternalModifiable valueInternal = (${VMFPKG_INT}.VObjectInternalModifiable)e; +valueInternal._vmf_setContainer(this); + +## // for-loop +## { // scope +## // release from old container & set new container +## //${VMFPKG_INT}.VObjectInternalModifiable valueInternal = (${VMFPKG_INT}.VObjectInternalModifiable)e; +## boolean done = false; + +## #foreach($pOfType in ${prop.genericType.findAllPropsThatContainType()})## // for-loop +## // PROP: ${pOfType.parent.typeName}.${pOfType.name} +## #if(!${pOfType.equals(${prop})})##---- if (prop!=pOfType) +## if(!done && valueInternal._vmf_getContainer() instanceof ${pOfType.parent.typeName}) { +## #else##--------------------------------## else (prop!=pOfType) +## // -> prop is identical to this prop. only remove if container instance is different from +## // 'this' reference +## if(!done && valueInternal._vmf_getContainer()!=this && valueInternal._vmf_getContainer() instanceof ${pOfType.parent.typeName}) { +## #end##---------------------------------## end (prop!=pOfType) +## ${pOfType.parent.typeName} container = (${pOfType.parent.typeName})valueInternal._vmf_getContainer(); +## #if(${pOfType.propType}=="COLLECTION")## if (is collection-type) +## container.get${pOfType.nameWithUpperCase}().remove(valueInternal); +## #else##---------------------------------## else (is collection-type) +## container.set${pOfType.nameWithUpperCase}(null); +## #end##----------------------------------## end (is collection-type) +## done = true; +## } +## #end##------------------------------------------------------------ // for-loop +## // valueInternal._vmf_setContainer(this); +## } // scope +## // for-loop + + + +## // remove element from previous collection +## // TODO use bulk operations if possible +## if(e.get${prop.containmentInfo.opposite.nameWithUpperCase}()!=null) { +## e.get${prop.containmentInfo.opposite.nameWithUpperCase}().get${prop.nameWithUpperCase}().remove(e); +## } +## +## #set($propertyToModifyValue = "e") +## #set($oppositeValue = "this") +## #set($codeIndentValue = " ") +## #set($disableFireEventValue=false) +## #parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "e") +#set($objectToRemoveReferenceOnValue = false) +#set($referenceToRemoveValue = false) +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.added() + + evt.removed().elements().forEach( (e) -> { + if(e==null) return; + + // release this container + ${VMFPKG_INT}.VObjectInternalModifiable oldValueInternal = (${VMFPKG_INT}.VObjectInternalModifiable)e; + oldValueInternal._vmf_setContainer(null); + + +## #set($propertyToModifyValue = "e") +## #set($oppositeValue = "null") +## #set($codeIndentValue = " ") +## #set($disableFireEventValue=false) +## #parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + +#set($objectToAddReferenceOnValue=false) +#set($referenceToAddValue = false) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "e") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.removed() + + }); // end of change listener + + } // end of "lazy init" if(this.__vmf_prop_$prop.name==null) + + return this.__vmf_prop_$prop.name; +#else +#if($prop.propType == "COLLECTION") + if(this.__vmf_prop_$prop.name==null) { + this.__vmf_prop_$prop.name = ${VCOLL_PKG}.VList.newInstance(new java.util.ArrayList<>()); +#if($prop.type||$prop.genericType) + this.__vmf_prop_${prop.name}.addChangeListener( (evt) -> { + evt.added().elements().forEach( (e) -> { + // nothing to do if e == null + if(e==null) return; +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "e") +#set($objectToRemoveReferenceOnValue = false) +#set($referenceToRemoveValue = false) + #set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.added() + + evt.removed().elements().forEach( (e) -> { + // nothing to do if e == null + if(e==null) return; +#set($objectToAddReferenceOnValue=false) +#set($referenceToAddValue = false) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "e") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + }); // end of evt.removed() + + }); // end of change listener +#end## if is model type + } // end of "lazy init" if(this.__vmf_prop_$prop.name==null) +#end + return this.__vmf_prop_$prop.name; + +#end + } // end of $prop.getterDeclaration +#end## not cross-ref prop +#end## foreach prop diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/remove-containment-opposites-collection.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/remove-containment-opposites-collection.vm new file mode 100644 index 00000000..37431142 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/remove-containment-opposites-collection.vm @@ -0,0 +1,71 @@ + + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainType() + // ---------------------------------------- + { // scope + + // cast to internal vobject which allows us to access its container + ${VMFPKG_INT}.VObjectInternalModifiable valueInternal = + (${VMFPKG_INT}.VObjectInternalModifiable)e; + + // indicates whether we found the prev property that contain this value + boolean done = false; + +#foreach($pOfType in ${prop.genericType.findAllPropsThatContainType()})## // for-loop + // PROP: ${pOfType.parent.typeName}.${pOfType.name} +#if(!${pOfType.equals(${prop})})##---- if (prop!=pOfType) + if(!done && valueInternal._vmf_getContainer() instanceof ${pOfType.parent.typeName}) { +#else##--------------------------------## else (prop!=pOfType) + // -> prop is identical to this prop. Only remove if container instance + // is different from 'this' reference + if( !done + && valueInternal._vmf_getContainer()!=this + && valueInternal._vmf_getContainer() instanceof ${pOfType.parent.typeName}) { +#end##---------------------------------## end (prop!=pOfType) + ${pOfType.parent.typeName} container = (${pOfType.parent.typeName})valueInternal._vmf_getContainer(); +#if(${pOfType.propType}=="COLLECTION")##-- if (is collection-type) + container.get${pOfType.nameWithUpperCase}().remove(valueInternal); +#else##---------------------------------## else (is collection-type) + container.set${pOfType.nameWithUpperCase}(null); +#end##----------------------------------## end (is collection-type) + // TODO 28.09.2019 maybe not allowed due to potential overlap // done = true; + } // end if (${pOfType.parent.typeName}.${pOfType.name}) +#end##------------------------------------------------------------ // for-loop + } // scope + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainType() + // ---------------------------------------- + + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainTypeWithOpposite() + // ---------------------------------------- + { // scope + // indicates whether we found the prev property that contain this value + boolean done = false; + +#foreach($pOfType in ${prop.genericType.findAllPropsThatContainTypeWithOpposite()})## // for-loop + // PROP: ${pOfType.parent.typeName}.${pOfType.name} + // CONTAINER: ${prop.name}.get${pOfType.containmentInfo.opposite.nameWithUpperCase}() +#if(!${pOfType.equals(${prop})})##---- if (prop!=pOfType) + if( !done + && e.get${pOfType.containmentInfo.opposite.nameWithUpperCase}()!=null) { +#else##--------------------------------## else (prop!=pOfType) + // -> prop is identical to this prop. Only remove if container instance + // is different from 'this' reference + if( !done + && e.get${pOfType.containmentInfo.opposite.nameWithUpperCase}()!=null + && e.get${pOfType.containmentInfo.opposite.nameWithUpperCase}()!=this) { +#end##---------------------------------## end (prop!=pOfType) + ${pOfType.parent.typeName} container = e.get${pOfType.containmentInfo.opposite.nameWithUpperCase}(); +#if(${pOfType.propType}=="COLLECTION")##-- if (is collection-type) + container.get${pOfType.nameWithUpperCase}().remove(e); +#else##---------------------------------## else (is collection-type) + container.set${pOfType.nameWithUpperCase}(null); +#end##----------------------------------## end (is collection-type) + // TODO 28.09.2019 maybe not allowed due to potential overlap // done = true; + } // end if (${pOfType.parent.typeName}.${pOfType.name}) +#end##------------------------------------------------------------ // for-loop + } // scope + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainTypeWithOpposite() + // ---------------------------------------- \ No newline at end of file diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/remove-containment-opposites.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/remove-containment-opposites.vm new file mode 100644 index 00000000..6e4dac42 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/remove-containment-opposites.vm @@ -0,0 +1,71 @@ + + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainType() + // ---------------------------------------- + { // scope + + // cast to internal vobject which allows us to access its container + ${VMFPKG_INT}.VObjectInternalModifiable valueInternal = + (${VMFPKG_INT}.VObjectInternalModifiable)$prop.name; + + // indicates whether we found the prev property that contain this value + boolean done = false; + +#foreach($pOfType in ${prop.type.findAllPropsThatContainType()})## // for-loop + // PROP: ${pOfType.parent.typeName}.${pOfType.name} +#if(!${pOfType.equals(${prop})})##---- if (prop!=pOfType) + if(!done && valueInternal._vmf_getContainer() instanceof ${pOfType.parent.typeName}) { +#else##--------------------------------## else (prop!=pOfType) + // -> prop is identical to this prop. Only remove if container instance + // is different from 'this' reference + if( !done + && valueInternal._vmf_getContainer()!=this + && valueInternal._vmf_getContainer() instanceof ${pOfType.parent.typeName}) { +#end##---------------------------------## end (prop!=pOfType) + ${pOfType.parent.typeName} container = (${pOfType.parent.typeName})valueInternal._vmf_getContainer(); +#if(${pOfType.propType}=="COLLECTION")##-- if (is collection-type) + container.get${pOfType.nameWithUpperCase}().remove(valueInternal); +#else##---------------------------------## else (is collection-type) + container.set${pOfType.nameWithUpperCase}(null); +#end##----------------------------------## end (is collection-type) + // TODO 28.09.2019 maybe not allowed due to potential overlap // done = true; + } // end if (${pOfType.parent.typeName}.${pOfType.name}) +#end##------------------------------------------------------------ // for-loop + } // scope + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainType() + // ---------------------------------------- + + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainTypeWithOpposite() + // ---------------------------------------- + { // scope + // indicates whether we found the prev property that contain this value + boolean done = false; + +#foreach($pOfType in ${prop.type.findAllPropsThatContainTypeWithOpposite()})## // for-loop + // PROP: ${pOfType.parent.typeName}.${pOfType.name} + // CONTAINER: ${prop.name}.get${pOfType.containmentInfo.opposite.nameWithUpperCase}() +#if(!${pOfType.equals(${prop})})##---- if (prop!=pOfType) + if( !done + && ${prop.name}.get${pOfType.containmentInfo.opposite.nameWithUpperCase}()!=null) { +#else##--------------------------------## else (prop!=pOfType) + // -> prop is identical to this prop. Only remove if container instance + // is different from 'this' reference + if( !done + && ${prop.name}.get${pOfType.containmentInfo.opposite.nameWithUpperCase}()!=null + && ${prop.name}.get${pOfType.containmentInfo.opposite.nameWithUpperCase}()!=this) { +#end##---------------------------------## end (prop!=pOfType) + ${pOfType.parent.typeName} container = ${prop.name}.get${pOfType.containmentInfo.opposite.nameWithUpperCase}(); +#if(${pOfType.propType}=="COLLECTION")##-- if (is collection-type) + container.get${pOfType.nameWithUpperCase}().remove($prop.name); +#else##---------------------------------## else (is collection-type) + container.set${pOfType.nameWithUpperCase}(null); +#end##----------------------------------## end (is collection-type) + // TODO 28.09.2019 maybe not allowed due to potential overlap // done = true; + } // end if (${pOfType.parent.typeName}.${pOfType.name}) +#end##------------------------------------------------------------ // for-loop + } // scope + // ---------------------------------------- + // -- for-loop p : findAllPropsThatContainTypeWithOpposite() + // ---------------------------------------- \ No newline at end of file diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/set-opposite-via-reflection.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/set-opposite-via-reflection.vm new file mode 100644 index 00000000..6f20e674 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/set-opposite-via-reflection.vm @@ -0,0 +1,91 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +#if($prop.propType == "COLLECTION") +${codeIndentValue}Object oldOpposite = ${codeIndentValue}((${prop.genericPackageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)${propertyToModifyValue}).__vmf_get_prop_${prop.containmentInfo.opposite.name}(); +${codeIndentValue}((${prop.genericPackageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)${propertyToModifyValue}).__vmf_set_prop_${prop.containmentInfo.opposite.name}($oppositeValue); +#if(!$disableFireEventValue) +${codeIndentValue}((${prop.genericPackageName}.impl.__VMF_TYPE_${prop.genericTypeName}Impl)${propertyToModifyValue})._vmf_firePropertyChangeIfListenersArePresent("${prop.containmentInfo.opposite.name}", oldOpposite, $oppositeValue); +#else## if disableFireEventValue +${codeIndentValue}// not generating change event (disableFireEventValue=$disableFireEventValue) +#end## if disableFireEventValue +#else## if prop type == COLLECTION +${codeIndentValue}Object oldOpposite = ${codeIndentValue}((${prop.packageName}.impl.__VMF_TYPE_${prop.simpleTypeName}Impl)${propertyToModifyValue}).__vmf_get_prop_${prop.containmentInfo.opposite.name}(); +${codeIndentValue}((${prop.packageName}.impl.__VMF_TYPE_${prop.simpleTypeName}Impl)${propertyToModifyValue}).__vmf_set_prop_${prop.containmentInfo.opposite.name}($oppositeValue); +#if(!$disableFireEventValue) +${codeIndentValue}((${prop.packageName}.impl.__VMF_TYPE_${prop.simpleTypeName}Impl)${propertyToModifyValue})._vmf_firePropertyChangeIfListenersArePresent("${prop.containmentInfo.opposite.name}", oldOpposite, $oppositeValue); +#else## if disableFireEventValue +${codeIndentValue}// not generating change event (disableFireEventValue=$disableFireEventValue) +#end## if disableFireEventValue +#end## if prop type == COLLECTION +## sets opposite field via reflection +## TODO since 18.02.2019 we try to use direct field access instead +## ${codeIndentValue}try { +## ${codeIndentValue} java.lang.reflect.Field field = +## ${codeIndentValue} ${propertyToModifyValue}.getClass().getDeclaredField("__vmf_prop_${prop.containmentInfo.opposite.name}"); +## ${codeIndentValue} field.setAccessible(true); +## ${codeIndentValue} Object oldOpposite = field.get(${propertyToModifyValue}); +## ${codeIndentValue} field.set(${propertyToModifyValue}, $oppositeValue); +## #if(!$disableFireEventValue) +## ${codeIndentValue} // generate change event (disableFireEventValue=$disableFireEventValue) +## ${codeIndentValue} java.lang.reflect.Method m = ${propertyToModifyValue}.getClass().getDeclaredMethod( +## ${codeIndentValue} "_vmf_firePropertyChangeIfListenersArePresent", +## ${codeIndentValue} String.class, Object.class, Object.class); +## ${codeIndentValue} m.setAccessible(true); +## ${codeIndentValue} m.invoke(${propertyToModifyValue}, +## ${codeIndentValue} "${prop.containmentInfo.opposite.name}", oldOpposite, $oppositeValue); +## #else## if disableFireEventValue +## ${codeIndentValue} // not generating change event (disableFireEventValue=$disableFireEventValue) +## #end## if disableFireEventValue +## ${codeIndentValue}} catch (Exception ex) { +## ${codeIndentValue} java.util.logging.Logger.getLogger( +## ${codeIndentValue} ${type.implementation.typeName}.class.getName()). +## ${codeIndentValue} log(java.util.logging.Level.SEVERE, null, ex); +## ${codeIndentValue} throw new RuntimeException("Reflection broken", ex); +## ${codeIndentValue}} + +## ${codeIndentValue}} catch (NoSuchFieldException ex) { +## ${codeIndentValue} java.util.logging.Logger.getLogger( +## ${codeIndentValue} ${type.implementation.typeName}.class.getName()). +## ${codeIndentValue} log(java.util.logging.Level.SEVERE, null, ex); +## ${codeIndentValue}} catch (SecurityException ex) { +## ${codeIndentValue} java.util.logging.Logger.getLogger( +## ${codeIndentValue} ${type.implementation.typeName}.class.getName()). +## ${codeIndentValue} log(java.util.logging.Level.SEVERE, null, ex); +## ${codeIndentValue}} catch (IllegalArgumentException ex) { +## ${codeIndentValue} java.util.logging.Logger.getLogger( +## ${codeIndentValue} ${type.implementation.typeName}.class.getName()). +## ${codeIndentValue} log(java.util.logging.Level.SEVERE, null, ex); +## ${codeIndentValue}} catch (IllegalAccessException ex) { +## ${codeIndentValue} java.util.logging.Logger.getLogger( +## ${codeIndentValue} ${type.implementation.typeName}.class.getName()). +## ${codeIndentValue} log(java.util.logging.Level.SEVERE, null, ex); +## ${codeIndentValue}} catch (NoSuchMethodException ex) { +## ${codeIndentValue} java.util.logging.Logger.getLogger( +## ${codeIndentValue} ${type.implementation.typeName}.class.getName()). +## ${codeIndentValue} log(java.util.logging.Level.SEVERE, null, ex); +## ${codeIndentValue}} catch (java.lang.reflect.InvocationTargetException ex) { +## ${codeIndentValue} java.util.logging.Logger.getLogger( +## ${codeIndentValue} ${type.implementation.typeName}.class.getName()). +## ${codeIndentValue} log(java.util.logging.Level.SEVERE, null, ex); +## ${codeIndentValue}} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/set-references.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/set-references.vm new file mode 100644 index 00000000..25597bd0 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/set-references.vm @@ -0,0 +1,47 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +## Used Variables: +## +## objectToAddReferenceOnValue +## referenceToAddValue +## referenceToRemoveValue +## objectToRemoveReferenceOnValue +## codeIndentValue +#if($prop.type||$prop.genericType) +#if(${referenceToAddValue}) +// TODO 17.02.2019 feature deactivated due to huge memory consumption +// ${codeIndentValue}if(${referenceToAddValue}!=null && ${objectToAddReferenceOnValue}!=null) { +// ${codeIndentValue}((${VMFPKG_INT}.VObjectInternal)${objectToAddReferenceOnValue})._vmf_references().add(${referenceToAddValue}); +// ${codeIndentValue}((${VMFPKG_INT}.VObjectInternal)${referenceToAddValue})._vmf_referencedBy().add(${objectToAddReferenceOnValue}); +// ${codeIndentValue}} +#end##end if $referenceToAdd!=null + +#if(${referenceToRemoveValue}) +// TODO 17.02.2019 feature deactivated due to huge memory consumption +// ${codeIndentValue}if(${referenceToRemoveValue}!=null && ${objectToRemoveReferenceOnValue}!=null) { +// ${codeIndentValue}((${VMFPKG_INT}.VObjectInternal)${objectToRemoveReferenceOnValue})._vmf_references().add(${referenceToRemoveValue}); +// ${codeIndentValue}((${VMFPKG_INT}.VObjectInternal)${referenceToRemoveValue})._vmf_referencedBy().add(${objectToRemoveReferenceOnValue}); +// ${codeIndentValue}} +#end##end if $referenceToRemoveValue!=null +#end## if is modelType diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/setter.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/setter.vm new file mode 100644 index 00000000..20731c8c --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/setter.vm @@ -0,0 +1,482 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +#foreach( $prop in ${type.implementation.propertiesWithoutCollectionsBasedContainment} ) +#if(${prop.propType}=="COLLECTION")## if (prop is collection type) +#else##-----------------------------## else (prop is collection type) +#if(${prop.containmentProperty})## if (containmentProperty) +#if(${prop.containmentInfo.withoutOpposite})## if (no opposite) +// ---------------------------------------- +// - containment-prop: +// -> prop is ref to contained object +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> opposite: false, +// ---------------------------------------- + @Override + public $prop.setterDeclaration { + + // return early if identical value has been set + if (this.__vmf_prop_$prop.name == $prop.name) { + return; + } + + // ---------------------------------------- + // save the old value + // ---------------------------------------- + ${prop.typeName} oldValue = this.__vmf_prop_$prop.name; + // ---------------------------------------- + + // release old container + if(oldValue!=null) { + ${VMFPKG_INT}.VObjectInternalModifiable oldValueInternal = + (${VMFPKG_INT}.VObjectInternalModifiable)oldValue; + oldValueInternal._vmf_setContainer(null); + } + + // release from old container & set new container + if($prop.name!=null) { + +#parse("${VMF_TEMPLATE_PATH}impl/remove-containment-opposites.vm") + + // cast to internal vobject which allows us to access its container + ${VMFPKG_INT}.VObjectInternalModifiable valueInternal = + (${VMFPKG_INT}.VObjectInternalModifiable)$prop.name; + + // finally, set 'this' as the container of the new value + valueInternal._vmf_setContainer(this); + + } // if ($prop.name!=null) + + // ---------------------------------------- + // set the new value + // ---------------------------------------- + this.__vmf_prop_$prop.name = $prop.name; + // ---------------------------------------- + + // ---------------------------------------- + // we fire a change event now + _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + // ---------------------------------------- + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "this.__vmf_prop_"+${prop.name}) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "oldValue") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + } // setterDeclaration (setter method) +#else##--------------------------------------else (no opposite) +######################################################################################################################## +#if(${prop.containmentInfo.containmentType}=="CONTAINED")## if (prop is contained) +#if(${prop.containmentInfo.opposite.propType}=="COLLECTION")## if (opposite is collection) +// ---------------------------------------- +// - containment-prop: +// -> prop is ref to contained object +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> opposite: true, ${prop.containmentInfo.opposite.typeName}.${prop.containmentInfo.opposite.name} +// -> propType: ${prop.containmentInfo.opposite.typeName} +// -> collection: false +// ---------------------------------------- +// FIXME: we cannot have a collection as parent container! +#else##-----------------------------------------------------## else (opposite is collection) +// ---------------------------------------- +// - containment-prop: +// -> prop is ref to contained object +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> opposite: true, ${prop.containmentInfo.opposite.typeName}.${prop.containmentInfo.opposite.name} +// -> propType: ${prop.containmentInfo.opposite.typeName} +// -> collection: false +// ---------------------------------------- + @Override + public $prop.setterDeclaration { + + // return early if identical value has been set + if (this.__vmf_prop_$prop.name == $prop.name) { + return; + } + + // ---------------------------------------- + // set the new value + // ---------------------------------------- + $prop.typeName oldValue = this.__vmf_prop_$prop.name; + this.__vmf_prop_$prop.name = $prop.name; + // ---------------------------------------- + + // we fire a change event later after setting up the new child property and releasing the old child + // (if this property is a containment child / contained or cross ref) + // _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + + // ---------------------------------------- + // containment property: + // ---------------------------------------- + // -> this is a single contained property (child) + // -> the opposite is a single container property (parent) + // ---------------------------------------- + + // + // if previous container is present then release containment relation + if(oldValue!=null) { + //(($prop.typeName$VMF_IMPL_CLASS_EXT)oldValue)._vmf_set${prop.containmentInfo.opposite.nameWithUpperCase}NoContainment(null); + +#set($disableFireEventValue=false) +#set($propertyToModifyValue = "oldValue") +#set($oppositeValue = "null") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + + } + + // if new container is present then update containment relation + if($prop.name!=null) { + //(($prop.typeName$VMF_IMPL_CLASS_EXT)$prop.name)._vmf_set${prop.containmentInfo.opposite.nameWithUpperCase}NoContainment(this); + + // remove '${prop.name}' object that shall be set from its previous parent + // if it has one. for collections we perform this operation in the getter + // method which registers a change listener that does all the work. + if(${prop.name}.get${prop.containmentInfo.opposite.nameWithUpperCase}()!=null) { + ${prop.name}.get${prop.containmentInfo.opposite.nameWithUpperCase}().set${prop.nameWithUpperCase}(null); + } + +#set($disableFireEventValue=false) +#set($propertyToModifyValue = "this.__vmf_prop_"+${prop.name}) +#set($oppositeValue = "this") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + + +#parse("${VMF_TEMPLATE_PATH}impl/remove-containment-opposites.vm") + +#if(${prop.containmentInfo.containmentType}=="CONTAINED") + // ---------------------------------------- + // (fire now, this property is a containment child / contained) + // ---------------------------------------- + _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + // ---------------------------------------- +#end## if contained + } +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "this.__vmf_prop_"+${prop.name}) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "oldValue") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + } // setterDeclaration (setter method) + +#end##------------------------------------------------------## end (opposite is collection) +######################################################################################################################## +#else##--------------------------------------------------## else (prop is contained) +#if(${prop.containmentInfo.opposite.propType}=="COLLECTION")## if (opposite is collection) +// ---------------------------------------- +// - containment-prop: +// -> prop is ref to container object +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> opposite: true, ${prop.containmentInfo.opposite.typeName}.${prop.containmentInfo.opposite.name} +// -> propType: ${prop.containmentInfo.opposite.typeName} +// -> collection: false +// ---------------------------------------- + @Override + public $prop.setterDeclaration { + + // ---------------------------------------- + // containment property: + // ---------------------------------------- + // -> this is a single property + // -> the opposite is a collection + // ---------------------------------------- + + // opposite is a collection type. we just need to add this to the + // opposite collection which will handle the containment just fine + + // nothing to do, values are identical + if(this.__vmf_prop_$prop.name == $prop.name) { + return; + } + + // remember the old value for change event generation + $prop.typeName oldValue = this.__vmf_prop_$prop.name; + + // remove this from previous opposite + if(this.__vmf_prop_$prop.name!=null) { + this.__vmf_prop_$prop.name.${prop.containmentInfo.opposite.getterPrefix}${prop.containmentInfo.opposite.nameWithUpperCase}().remove(this); + } + + // add this to new opposite + if($prop.name!=null) { + $prop.name.${prop.containmentInfo.opposite.getterPrefix}${prop.containmentInfo.opposite.nameWithUpperCase}().add(this); + } + + // fire property change event + // _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + } + +#else##-----------------------------------------------------## else (opposite is collection) +// ---------------------------------------- +// - containment-prop: +// -> prop is ref to container object +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> opposite: true, ${prop.containmentInfo.opposite.typeName}.${prop.containmentInfo.opposite.name} +// -> propType: ${prop.containmentInfo.opposite.typeName} +// -> collection: false +// ---------------------------------------- + @Override + public $prop.setterDeclaration { + + // return early if identical value has been set + if (this.__vmf_prop_$prop.name == $prop.name) { + return; + } + + // ---------------------------------------- + // set the new value + // ---------------------------------------- + $prop.typeName oldValue = this.__vmf_prop_$prop.name; + this.__vmf_prop_$prop.name = $prop.name; + // ---------------------------------------- + + // ---------------------------------------- + // we fire a change event now + // (if this property is a normal property or a containment parent / container) + _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + // ---------------------------------------- + + // ---------------------------------------- + // containment property: + // ---------------------------------------- + // -> this is a single container property (parent) + // -> the opposite is a single contained property (child) + // ---------------------------------------- + + // if previous container is present then release containment relation + if(oldValue!=null) { + // (($prop.typeName$VMF_IMPL_CLASS_EXT)oldValue)._vmf_set${prop.containmentInfo.opposite.nameWithUpperCase}NoContainment(null); +#set($disableFireEventValue=false) +#set($propertyToModifyValue = "oldValue") +#set($oppositeValue = "null") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + } + + // if new container is present then update containment relation + if($prop.name!=null) { + // (($prop.typeName$VMF_IMPL_CLASS_EXT)$prop.name)._vmf_set${prop.containmentInfo.opposite.nameWithUpperCase}NoContainment(this); + +#set($disableFireEventValue=false) +#set($propertyToModifyValue = "this.__vmf_prop_"+${prop.name}) +#set($oppositeValue = "this") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-opposite-via-reflection.vm") + } + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "this.__vmf_prop_"+${prop.name}) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "oldValue") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + } // setterDeclaration (setter method) + +#end##------------------------------------------------------## end (opposite is collection) +#end##---------------------------------------end (no opposite) +######################################################################################################################## +#end##---------------------------------------------------## end (prop is contained) +#else##----------------------------else (containmentProperty) +#if(${prop.crossRefProperty})##--------------if (crossref prop) +#if(${prop.referenceInfo.opposite.propType}=="COLLECTION")##---if (opposite is collection) +// ---------------------------------------- +// - cross-ref: +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> opposite: true, ${prop.referenceInfo.opposite.typeName}.${prop.referenceInfo.opposite.name} +// -> propType: ${prop.referenceInfo.opposite.typeName} +// -> collection: true +// ---------------------------------------- + @Override + public $prop.setterDeclaration { + + // return early if identical value has been set + if (this.__vmf_prop_$prop.name == $prop.name) { + return; + } + + // ---------------------------------------- + // store the old value ... + // ---------------------------------------- + $prop.typeName oldValue = this.__vmf_prop_$prop.name; + + // ---------------------------------------- + if(oldValue!=null) { + String eventInfo = oldValue.get${prop.referenceInfo.opposite.nameWithUpperCase}().getEventInfo(); + oldValue.get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF); + oldValue.get${prop.referenceInfo.opposite.nameWithUpperCase}().remove(this); + oldValue.get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(eventInfo); + } + + // ---------------------------------------- + // ... and set the new value + // ---------------------------------------- + this.__vmf_prop_$prop.name = $prop.name; + + _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + + if(this.__vmf_prop_${prop.name}!=null) { + String eventInfo = this.__vmf_prop_${prop.name}.get${prop.referenceInfo.opposite.nameWithUpperCase}().getEventInfo(); + this.__vmf_prop_${prop.name}.get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF); + this.__vmf_prop_${prop.name}.get${prop.referenceInfo.opposite.nameWithUpperCase}().add(this); + this.__vmf_prop_${prop.name}.get${prop.referenceInfo.opposite.nameWithUpperCase}().setEventInfo(eventInfo); + } + + // ---------------------------------------- + // we are a cross-ref property and need to fire after updating the other prop to allow event propagation + // fire property change event + // ---------------------------------------- + if(oldValue!=this.__vmf_prop_$prop.name) { +// _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + } + // ---------------------------------------- + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "this.__vmf_prop_"+${prop.name}) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "oldValue") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + } // setterDeclaration (setter method) +#else##--------------------------------------------------##----else (opposite is collection) +// ---------------------------------------- +// - cross-ref: +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> opposite: true, ${prop.referenceInfo.opposite.typeName}.${prop.referenceInfo.opposite.name} +// -> propType: ${prop.referenceInfo.opposite.typeName} +// -> collection: false +// ---------------------------------------- + @Override + public $prop.setterDeclaration { + + // return early if identical value has been set + if (this.__vmf_prop_$prop.name == $prop.name) { + return; + } + + // ---------------------------------------- + // set the new value + // ---------------------------------------- + $prop.typeName oldValue = this.__vmf_prop_$prop.name; + this.__vmf_prop_$prop.name = $prop.name; + // ---------------------------------------- + + if(oldValue!=null) { + oldValue.set${prop.referenceInfo.opposite.nameWithUpperCase}(null); + } + _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + if(this.__vmf_prop_${prop.name}!=null) { + Object refOldVal = ((__VMF_TYPE_${prop.type.implementation.typeName})this.__vmf_prop_${prop.name}).__vmf_get_prop_${prop.referenceInfo.opposite.name}(); + ((__VMF_TYPE_${prop.type.implementation.typeName})this.__vmf_prop_${prop.name}).__vmf_set_prop_${prop.referenceInfo.opposite.name}(this); + // fire property change event + if(refOldVal != this) { + ((__VMF_TYPE_${prop.type.implementation.typeName})this.__vmf_prop_${prop.name})._vmf_firePropertyChangeIfListenersArePresent("${prop.referenceInfo.opposite.name}", refOldVal, this, ${VMFPKG_INT}.ChangeInternal.CHANGE_TYPE_CROSS_REF); + } + } + + // ---------------------------------------- + // we are a cross-ref property and need to fire after updating the other prop to allow event propagation + // fire property change event + // ---------------------------------------- + if(oldValue!=this.__vmf_prop_$prop.name) { +// _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + } + // ---------------------------------------- + +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "this.__vmf_prop_"+${prop.name}) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "oldValue") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + } // setterDeclaration (setter method) +#end##---------------------------------------------------##----end (opposite is collection) +#else##--------------------------------------else (crossref prop) +// ---------------------------------------- +// - normal prop: +// -> prop: +// -> name: ${prop.name} +// -> propType: ${prop.typeName} +// -> collection: false, ${prop.propType} +// -> opposite: false, +// ---------------------------------------- + @Override + public $prop.setterDeclaration { + + // return early if identical value has been set + if (this.__vmf_prop_$prop.name == $prop.name) { + return; + } + + // ---------------------------------------- + // set the new value + // ---------------------------------------- + $prop.typeName oldValue = this.__vmf_prop_$prop.name; + this.__vmf_prop_$prop.name = $prop.name; + // ---------------------------------------- + // ---------------------------------------- + // we fire a change event now + // (if this property is a normal property or a containment parent / container) + _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); + // ---------------------------------------- +#set($objectToAddReferenceOnValue="this") +#set($referenceToAddValue = "this.__vmf_prop_"+${prop.name}) +#set($objectToRemoveReferenceOnValue = "this") +#set($referenceToRemoveValue = "oldValue") +#set($codeIndentValue = " ") +#parse("${VMF_TEMPLATE_PATH}impl/set-references.vm") + } // setterDeclaration (setter method) +#end##---------------------------------------end (crossref prop) +#end##-----------------------------end (containmentProperty) + +#if($prop.containmentProperty && ${prop.propType}!="COLLECTION") +// TODO do we still need this? // internal API +// TODO do we still need this? void _vmf_set${prop.nameWithUpperCase}NoContainment($prop.typeName $prop.name) { +// TODO do we still need this? // set the new value +// TODO do we still need this? $prop.typeName oldValue = this.__vmf_prop_$prop.name; +// TODO do we still need this? this.__vmf_prop_$prop.name = $prop.name; +// TODO do we still need this? +// TODO do we still need this? // fire property change event +// TODO do we still need this? _vmf_firePropertyChangeIfListenersArePresent("$prop.name", oldValue, this.__vmf_prop_$prop.name); +// TODO do we still need this? } + + +#end## end if containment property and no collection +#end##------------------------------## end (prop is collection type) +#end## end for-each \ No newline at end of file diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/sync.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/sync.vm new file mode 100644 index 00000000..239fb623 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/sync.vm @@ -0,0 +1,127 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +// DEPRECATED: since 22.03.2017 +// TYPE: $prop.type +// SYNCINFO: $prop.syncInfo +#if($prop.syncInfo) +// OPPOSITE: ${prop.syncInfo.other.typeName} +// EXTENDS: $type.extendsType(${prop.syncInfo.other}) +#else +// OPPOSITE: null +// EXTENDS: null +#end + +#if($prop.syncInfo && $type.extendsType(${prop.syncInfo.other})) + + if(!_vmf_syncDisabled[$prop.propId]) { + + // -------------- Sync (added elements) -------------- + + // disable sync in opposite to prevent rebounce + this._vmf_syncDisabled[${prop.syncInfo.opposite.propId}] = true; + + java.util.List indicesInOpposite = new java.util.ArrayList<>(); + + ${VCOLL_PKG}.VList<${prop.syncInfo.opposite.genericTypeName}> oppositeList = + this.${prop.syncInfo.opposite.getterPrefix}${prop.syncInfo.opposite.nameWithUpperCase}(); + ${VCOLL_PKG}.VList<${prop.genericTypeName}> ourList = + this.${prop.getterPrefix}${prop.nameWithUpperCase}(); + + java.util.List<${prop.syncInfo.opposite.genericTypeName}> elementsToSync = + new java.util.ArrayList<>(); + + for(int i = 0; i < evt.added().indices().length;i++) { + + // if element is not compatible we skip it + if(!(evt.added().elements().get(i) instanceof $prop.syncInfo.opposite.genericTypeName)) { + continue; + } + + int index = evt.added().indices()[i]; + + int typeCount = 0; + for(int j = index; j > -1 && !ourList.isEmpty(); j--) { + if(ourList.get(j) instanceof $prop.syncInfo.opposite.genericTypeName) { + typeCount++; + } + } + + typeCount = Math.max(0, typeCount-1); + + indicesInOpposite.add(typeCount); + elementsToSync.add(($prop.syncInfo.opposite.genericTypeName)evt.added().elements().get(i)); + } // end for each index + + ## for(int i = 0; i < indicesInOpposite.size; i++) { + ## int index = indicesInOpposite[i]; + ## if(index >= oppositeList.size()) { + ## + ## } + ## } // end for each index + + oppositeList.addAll(indicesInOpposite.stream().mapToInt(i -> i).toArray(), elementsToSync); + + } // end if sync is not disabled + + if(!_vmf_syncDisabled[$prop.propId]) { + + // -------------- Sync (removed elements) -------------- + + // disable sync in opposite to prevent rebounce + this._vmf_syncDisabled[${prop.syncInfo.opposite.propId}] = true; + + java.util.List indicesInOpposite = new java.util.ArrayList<>(); + + ${VCOLL_PKG}.VList<${prop.syncInfo.opposite.genericTypeName}> oppositeList = + this.${prop.syncInfo.opposite.getterPrefix}${prop.syncInfo.opposite.nameWithUpperCase}(); + ${VCOLL_PKG}.VList<${prop.genericTypeName}> ourList = + this.${prop.getterPrefix}${prop.nameWithUpperCase}(); + + for(int i = 0; i < evt.removed().indices().length;i++) { + + // if element is not compatible we skip it + if(!(evt.removed().elements().get(i) instanceof $prop.syncInfo.opposite.genericTypeName)) { + continue; + } + + int index = evt.removed().indices()[i]; + + int typeCount = 0; + for(int j = index; j > -1 && !ourList.isEmpty(); j--) { + if(ourList.get(j) instanceof $prop.syncInfo.opposite.genericTypeName) { + typeCount++; + } + } + + typeCount = Math.max(0, typeCount-1); + + indicesInOpposite.add(typeCount); + } + + oppositeList.removeAll(indicesInOpposite.stream().mapToInt(i -> i).toArray()); + + // we are done, enable sync in opposite + this._vmf_syncDisabled[${prop.syncInfo.opposite.propId}] = false; + } // end if sync is not disabled +#end##if syncInfo diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/to-string.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/to-string.vm new file mode 100644 index 00000000..73243575 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/impl/to-string.vm @@ -0,0 +1,110 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# + // --------------------------- BEGIN TO_STRING ----------------------------- +#if(${type.isToStringMethodDelegated()}) + // -> toString() method is delegated + public void __vmf_toString(StringBuilder sb, java.util.IdentityHashMap _vmf_fToStringChecker) { + sb.append(toString()); + } +#else## #if(${type.isToStringMethodDelegated()}) + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + java.util.IdentityHashMap _vmf_fToStringChecker = new java.util.IdentityHashMap<>(); + __vmf_toString(sb, _vmf_fToStringChecker); + _vmf_fToStringChecker.clear(); + _vmf_fToStringChecker = null; + return sb.toString(); + } + + @Override + public void __vmf_toString(StringBuilder sb, java.util.IdentityHashMap _vmf_fToStringChecker) { + + { // begin + // test if "this" has been seen before + // implementation based on http://stackoverflow.com/a/11300376/1493549 + boolean isImmutable = (this instanceof eu.mihosoft.vmf.runtime.core.Immutable); + if (!isImmutable && _vmf_fToStringChecker.containsKey(this)) { + sb.append("{skipping recursion}"); + return; + } else { + if(!isImmutable) { + _vmf_fToStringChecker.put(this, null); + } + } + + sb.append("{\"@type\":\"$type.typeName\""); + +#foreach ($prop in $type.implementation.properties) +#if (${prop.isIgnoredForToString()} == false) +#if (${prop.containmentInfo.containmentType} != "CONTAINER" ) +#if ( ${prop.propType} == "COLLECTION" ) + + // -- writing collection param '$prop.name' + // + sb.append(", \"$prop.name\": "); + if(this.__vmf_prop_${prop.name}==null) { + sb.append("[]"); + } else { + sb.append("["); + for(int i = 0; i < this.__vmf_prop_${prop.name}.size(); i++) { + if(i>0) sb.append(", "); + Object lEntry = this.__vmf_prop_${prop.name}.get(i); + if(lEntry instanceof ${VMFPKG_INT}.VObjectInternal) { + ${VMFPKG_INT}.VObjectInternal lEntryVobj = (${VMFPKG_INT}.VObjectInternal) lEntry; + lEntryVobj.__vmf_toString(sb, _vmf_fToStringChecker); + } else { + sb.append(lEntry); + } + } // end for + sb.append("]"); + } +#else + + // -- writing param '$prop.name' + { + + Object propObj = this.__vmf_prop_${prop.name}; + sb.append(", \"$prop.name\": \""); + if(propObj instanceof ${VMFPKG_INT}.VObjectInternal) { + ${VMFPKG_INT}.VObjectInternal propVobj = (${VMFPKG_INT}.VObjectInternal) propObj; + propVobj.__vmf_toString(sb, _vmf_fToStringChecker); + } else { + sb.append(propObj); + } + sb.append("\""); + } // end param +#end ## if contained and collection +#end ## end if container type +#end ## end if not ignore for toString +#end ## for-each property + sb.append("}"); + + } // end + } + + // end toString() +#end## #if(${type.isToStringMethodDelegated()}) + // ---------------------------- END TO_STRING ------------------------------ diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/implementation.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/implementation.vm new file mode 100644 index 00000000..8e8aa190 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/implementation.vm @@ -0,0 +1,343 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${type.implementation.packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal.*; +//import ${VCOLL_PKG}.*; +import ${type.packageName}.*; +//import java.beans.PropertyChangeSupport; +//import java.beans.PropertyChangeListener; +//import java.util.Objects; +//import java.util.Arrays; + +// property types imports +#foreach( $import in $type.implementation.imports ) +import $import; +#end + +// implementation + +/** + * An implementation of the model object {@code $type.fullTypeName}. + */ +@SuppressWarnings("deprecation") +class $type.implementation.typeName implements ${type.typeName}, __VMF_TYPE_$type.implementation.typeName, ${VMFPKG_INT}.VObjectInternalModifiable, VCloneableInternal { + + // -------------------------------------------------------------------- + // --- declaration of member variables + // -------------------------------------------------------------------- + +#parse("${VMF_TEMPLATE_PATH}impl/declare-props.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/declare-delegates.vm") + + private ${VMFPKG_INT}.VMFPropertyChangeSupport propertyChanges; + + // // TODO 17.02.2019 feature deactivated due to huge memory consumption + // referenced by + // private final ${VCOLL_PKG}.VList<${VMFPKG}.VObject> referencedBy = ${VCOLL_PKG}.VList.newInstance(new java.util.ArrayList<>()); + // references + // private final ${VCOLL_PKG}.VList<${VMFPKG}.VObject> references = ${VCOLL_PKG}.VList.newInstance(new java.util.ArrayList<>()); + + // -------------------------------------------------------------------- + // --- public constructors + // -------------------------------------------------------------------- + + public ${type.implementation.typeName}() { +#parse("${VMF_TEMPLATE_PATH}impl/constructor-delegates.vm") + +// -------------------------------------------------------------------- +// --- initialization of default values +// -------------------------------------------------------------------- +#foreach($prop in $type.implementation.properties) + // ---------- + // property id=${foreach.index} , name='${prop.name}' +#if(${prop.getDefaultValueAsString()}!="null") + __vmf_prop_$prop.name = ${prop.getDefaultValueAsString()}; + // TODO 26.01.2019 which one should we use? _vmf_setPropertyValueById(${foreach.index}, ${prop.getDefaultValueAsString()}); +#else##if default is present + // -> no default value is present +#end## if default is present +#end## for-each property + + } + + // -------------------------------------------------------------------- + // --- public getter methods for accessing properties + // -------------------------------------------------------------------- + +#parse("${VMF_TEMPLATE_PATH}impl/getter.vm") + + // -------------------------------------------------------------------- + // --- public setter methods for setting properties + // -------------------------------------------------------------------- + +#parse("${VMF_TEMPLATE_PATH}impl/setter.vm") + + // -------------------------------------------------------------------- + // --- Object methods (equals(), toString() etc.) + // -------------------------------------------------------------------- + +#parse("${VMF_TEMPLATE_PATH}impl/to-string.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/equals.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/clone.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/builder.vm") + +#parse("${VMF_TEMPLATE_PATH}impl/delegation-methods.vm") + + // -------------------------------------------------------------------- + // --- Utility methods + // -------------------------------------------------------------------- + + @Override + public void addPropertyChangeListener(java.beans.PropertyChangeListener l) { + _vmf_getPropertyChanges().addPropertyChangeListener(l); + } + @Override + public void removePropertyChangeListener(java.beans.PropertyChangeListener l) { + _vmf_getPropertyChanges().removePropertyChangeListener(l); + + if(_vmf_getPropertyChanges().getPropertyChangeListeners().length==0) { + propertyChanges = null; + } + } + + private ${VMFPKG_INT}.VMFPropertyChangeSupport _vmf_getPropertyChanges() { + + if(propertyChanges==null) { + propertyChanges = ${VMFPKG_INT}.VMFPropertyChangeSupport.newInstance(this); + } + + return propertyChanges; + } + + private boolean _vmf_hasListeners() { + return propertyChanges!=null; + } + + @Override + public void _vmf_firePropertyChangeIfListenersArePresent( + String propertyName, Object oldValue, Object newValue, String evtInfo) { + if(_vmf_hasListeners()) { + _vmf_getPropertyChanges(). + firePropertyChange(propertyName, oldValue, newValue, evtInfo); + } + } + + // -------------------------------------------------------------------- + // --- Public VMF API + // -------------------------------------------------------------------- + + private ${VMFPKG}.VMF vmf; + + @Override + public ${VMFPKG}.VMF vmf() { + if(vmf==null) { + vmf = new ${VMFPKG}.VMF() { + public ${VMFPKG}.Content content() { + return new ${VMFPKG}.Content() { + public ${VMFPKG}.VIterator iterator() { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this); + } + public java.util.stream.Stream<${VMFPKG}.VObject> stream() { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this).asStream(); + } + + public ${VMFPKG}.VIterator iterator(${VMFPKG}.VIterator.IterationStrategy strategy) { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this, strategy); + } + public java.util.stream.Stream<${VMFPKG}.VObject> stream(${VMFPKG}.VIterator.IterationStrategy strategy) { + return ${VMFPKG}.VIterator.of(${type.implementation.typeName}.this, strategy).asStream(); + } + public java.util.stream.Stream stream(Class type) { + return stream().filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e); + } + public java.util.stream.Stream stream(Class type, ${VMFPKG}.VIterator.IterationStrategy strategy) { + return stream(strategy).filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e); + } + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> referencedBy() { + return _vmf_referencedBy().asUnmodifiable(); + } + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> references() { + return _vmf_references().asUnmodifiable(); + } + + @Override + public ${type.typeName} deepCopy() { + java.util.IdentityHashMap identityMap = + new java.util.IdentityHashMap<>(); + return _vmf_deepCopy(identityMap); + } + + @Override + public ${type.typeName} shallowCopy() { + return ${type.implementation.typeName}. + this._vmf_shallowCopy(new java.util.IdentityHashMap<>()); + } + + @Override + public boolean equals(Object o) { + // vmf object comparison + return ${type.implementation.typeName}.this._vmf_equals(o); + } + + @Override + public int hashCode() { + // vmf object hash-code + return ${type.implementation.typeName}.this._vmf_hashCode(); + } + }; // end of Content class + } // end of content() + + private ${VMFPKG_INT}.ChangesImpl changes; + + public ${VMFPKG}.Changes changes() { + if (changes==null) { + changes = new ${VMFPKG_INT}.ChangesImpl(); + changes.setModel(${type.implementation.typeName}.this); + } + + return changes; + } + + private ${VMFPKG_INT}.ReflectImpl reflect; + + public ${VMFPKG}.Reflect reflect() { + if (reflect==null) { + reflect = new ${VMFPKG_INT}.ReflectImpl(); + reflect.setModel(${type.implementation.typeName}.this); + } + + return reflect; + } + + + }; // end vmf + } // end if null + + return vmf; + } + + private ${type.readOnlyInterface.typeName} readOnlyInstance; + + @Override + public ${type.readOnlyInterface.typeName} asReadOnly() { + + if(readOnlyInstance==null) { + readOnlyInstance = new ${type.readOnlyImplementation.packageName}. + ${type.readOnlyImplementation.typeName}(this); + } + + return readOnlyInstance; + } + + // -------------------------------------------------------------------- + // --- Reflection methods + // -------------------------------------------------------------------- + + // type id for improved reflection performance + public static final int _VMF_TYPE_ID = $type.typeId; + + @Override + public int _vmf_getTypeId() { + return _VMF_TYPE_ID; + } + + // Type info + @Override + public ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type _vmf_getType() { + return ${type.packageName}.${type.typeName}.type(); + } + +#parse("${VMF_TEMPLATE_PATH}reflection/reflection.vm") + + // -------------------------------------------------------------------- + // --- Id related methods + // -------------------------------------------------------------------- + + // id management is currently not part of VMF (TODO how should we support this?) + + // -------------------------------------------------------------------- + // --- Reference methods + // -------------------------------------------------------------------- + + @Override + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> _vmf_referencedBy() { + // TODO 17.02.2019 feature deactivated due to huge memory consumption + // return this.referencedBy; + throw new UnsupportedOperationException("TODO 17.02.2019 feature deactivated due to huge memory consumption"); + } + @Override + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> _vmf_references() { + // TODO 17.02.2019 feature deactivated due to huge memory consumption + // return this.references; + throw new UnsupportedOperationException("TODO 17.02.2019 feature deactivated due to huge memory consumption"); + } + +} + +// Internal Interface which gives access to impl features used in a 'multi-inheritance' context. +// Rationale: +// - we cannot cast to the implementation class to get access to impl features +// such as direct/raw property access since we simulate multiple inheritance +// - previously we just used reflection to circumvent the problem but this +// came at a huge performance cost +// - this interface supports multiple inheritance of impl features and +// gives access to properties without reflection which results in a huge +// performance improvement (up to 10x) +interface __VMF_TYPE_${type.implementation.typeName} extends ${type.typeName}${type.vmfTypeIfaceImplementzString} { + +#foreach( $prop in ${type.implementation.properties}) + +#if(${prop.isInheritedProp()})## if inheritedprop +// --- PROP '$prop.name : $prop.typeName' , Inherited from: '${prop.inheritedProp.parent.typeName}.${prop.inheritedProp.name}' + void __vmf_set_prop_${prop.name}(${prop.inheritedProp.typeName} obj); +#else##------------------------- else inheritedprop +// --- PROP '$prop.name : $prop.typeName' + void __vmf_set_prop_${prop.name}($prop.typeName obj); +#end##-------------------------- end inheritedprop + $prop.typeName __vmf_get_prop_${prop.name}(); +#if(${prop.crossRefProperty} && ${prop.propType} == "COLLECTION") + java.util.List<${prop.genericTypeName}> __vmf_get_prop_${prop.name}__vmf_RawList(); +#end## cross-ref collection +#end + + default void _vmf_firePropertyChangeIfListenersArePresent( + String propertyName, Object oldValue, Object newValue + ) { + _vmf_firePropertyChangeIfListenersArePresent(propertyName, oldValue, newValue, ""); + } + + void _vmf_firePropertyChangeIfListenersArePresent( + String propertyName, Object oldValue, Object newValue, String evtInfo + ); + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface.vm new file mode 100644 index 00000000..7ee35671 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface.vm @@ -0,0 +1,168 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${type.packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// TODO see issue #9 import ${VCOLL_PKG}.*; + +// property types imports +#foreach( $import in $type.imports ) +// import $import; +#end + +// interface + +/** + *#if($type.interfaceOnly) An interface-only#else A#end representation of the model object {@code $type.fullTypeName}. + * + * +#if(${type.documented}) + *

${type.customDocumentation}

+#else + * + * +#end + * + * + */ +public interface $type.typeName extends ${VMFPKG}.VObject$type.implementsString, Cloneable#if(!$type.interfaceOnly), ${VMFPKG}.Mutable#end { +#foreach( $prop in ${type.interface.properties} ) + +#parse("${VMF_TEMPLATE_PATH}interface/getter.vm") +#parse("${VMF_TEMPLATE_PATH}interface/setter.vm") + +#end## for each + +#parse("${VMF_TEMPLATE_PATH}interface/delegation-methods.vm") + +#if(!$type.interfaceOnly) + + /** + * Returns the Type object of this model type. + * @return Type object + */ + static ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type type() { + return __VMF__${type.typeName}_Creator.getType(); + } + +#parse("${VMF_TEMPLATE_PATH}interface/builder.vm") + + /** + * Creates a new instance of '{@link ${type.typeName} ${type.typeName}}' + * @return a new instance of '{@link ${type.typeName} ${type.typeName}}' + */ + static ${type.typeName} newInstance() { + return __VMF__${type.typeName}_Creator.newInstance(); + } +#end##if type interface only + + /** + * Returns a read-only wrapper of '{@link ${type.typeName} ${type.typeName}}' + * @return a read-only wrapper of '{@link ${type.typeName} ${type.typeName}}' + */ + ${type.readOnlyInterface.typeName} asReadOnly(); + + /** + * Returns a deep clone of this object. + * @return a deep clone of this object + */ + @Override + $type.typeName clone() /*throws CloneNotSupportedException*/; + +} + +#if(!$type.interfaceOnly) +/* + * Creates instances of type {@code ${type.implementation.packageName}.${type.implementation.typeName}}. Method handles + * and class objects are lazily initialized and cached since repetitive and high frequent usage is likely. + * + * This class is used to gain efficient avvess to private classes from the impl package. + */ +class __VMF__${type.typeName}_Creator { + + static Class cls; + static java.lang.reflect.Constructor constructor; + static java.lang.invoke.MethodHandles.Lookup lookup; + static java.lang.invoke.MethodHandle constructorMH; + + static ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type type; + + static ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type getType() { + if(type ==null) { + type = ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type.newInstance(true, false, "${type.packageName}.$type.typeName", ${type.packageName}.${type.typeName}.class); + } + return type; + } + + static ${type.typeName} newInstance() { + try { + + if(cls==null) { + cls = Class.forName("${type.implementation.packageName}.${type.implementation.typeName}"); + + if(lookup==null) { lookup = java.lang.invoke.MethodHandles.lookup(); } + + constructor = cls.getConstructor(); + constructor.setAccessible(true); + + constructorMH = lookup.unreflectConstructor(constructor); + } + + return (${type.typeName}) constructorMH.invoke(); + + } catch (Throwable tr) { + throw new RuntimeException("Cannot instantiate \"${type.implementation.packageName}.${type.implementation.typeName}\"", tr); + } + } + + static Class builderCls; + static java.lang.reflect.Constructor builderConstructor; + static java.lang.invoke.MethodHandle builderConstructorMH; + + static ${type.typeName}.Builder newBuilderInstance() { + try {#set ( $dollar_sign = "$") + + if(builderCls==null) { + builderCls = Class.forName("${type.implementation.packageName}.${type.implementation.typeName}${dollar_sign}Builder${VMF_IMPL_CLASS_EXT}"); + + if(lookup==null) { lookup = java.lang.invoke.MethodHandles.lookup(); } + + builderConstructor = builderCls.getConstructor(); + builderConstructor.setAccessible(true); + + builderConstructorMH = lookup.unreflectConstructor(builderConstructor); + } + + return (${type.typeName}.Builder) builderConstructorMH.invoke(); + + } catch (Throwable tr) { + throw new RuntimeException("Cannot instantiate \"${type.implementation.packageName}.${type.implementation.typeName}\"", tr); + } + } +} + +#end##if type interface only diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/builder.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/builder.vm new file mode 100644 index 00000000..7cbbf7df --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/builder.vm @@ -0,0 +1,92 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +// -------------------------------------------------------------------- +// --- Builder methods +// -------------------------------------------------------------------- + + public static interface Builder { + +#foreach( $prop in ${type.implementation.properties} ) +#if(!$prop.containmentProperty || ${prop.containmentInfo.containmentType}!="CONTAINER") + /** + * Sets the '${prop.name}' property of this builder. + * @param ${prop.name} value to set + * @return this builder + */ +#if($prop.propType == "COLLECTION") + public Builder with${prop.nameWithUpperCase}(java.util.List<${prop.genericPackageName}.${prop.genericTypeName}> ${prop.name}); + /** + * Sets the '${prop.name}' property of this builder. + * @param ${prop.name} values to set + * @return this builder + */ + public Builder with${prop.nameWithUpperCase}(${prop.genericPackageName}.${prop.genericTypeName}... ${prop.name}); +#else## #if($prop.propType == "COLLECTION") + public Builder with${prop.nameWithUpperCase}(${prop.typeName} ${prop.name}); +#end## #if($prop.propType == "COLLECTION") +#end## if type is no container or property is no containment type +#end##end foreach property + + /** + * Builds a new '{@link $type.fullTypeName ${type.typeName}}' instance. + * @return a new '{@link $type.fullTypeName ${type.typeName}}' instance + */ + public $type.typeName build(); + +#if(!$type.immutable) + /** + * Defines whether to append collections rather than replacing them in the + * {@link #[[#]]#applyFrom($type.typeName)} and {@link #[[#]]#applyTo($type.typeName)} methods. + * @param value that indicates whether to append collections + * @return this builder + */ + public Builder appendCollections(boolean value); + + /** + * Applies all properties from the specified object to this builder. + * @param o object to apply properties from + * @return this builder + * @see #[[#]]#applyTo($type.typeName) + */ + public Builder applyFrom($type.typeName o); + + /** + * Applies all properties from this builder to the specified object. + * @param o object to apply properties to + * @return this builder + * @see #[[#]]#applyFrom($type.typeName) + */ + public Builder applyTo($type.typeName o); +#end## if type is not immutable + + } // end class Builder + + /** + * Returns a new builder for creating a '{@link $type.fullTypeName ${type.typeName}}' instance. + * @return a new builder for creating a '{@link $type.fullTypeName ${type.typeName}}' instance + */ + static Builder newBuilder() { + return __VMF__${type.typeName}_Creator.newBuilderInstance(); + } // end newBuilder() + diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/delegation-methods.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/delegation-methods.vm new file mode 100644 index 00000000..3b5ef1fc --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/delegation-methods.vm @@ -0,0 +1,38 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +// -------------------------------------------------------------------- +// --- declaration of delegation methods +// -------------------------------------------------------------------- + +#foreach( $delegate in ${type.methodDelegations}) +#if($delegate.methodName != "clone") + /** +#if($delegate.documented) + *

${delegate.customDocumentation}

+#end## is documented + *

Note: The behavior of this method is defined by '{@link ${delegate.fullTypeName}}'.

+ */ + $delegate.methodDeclaration; +#end## #if($delegate.methodName != "clone") +#end## for each delegate diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/getter.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/getter.vm new file mode 100644 index 00000000..6b7c3b4f --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/getter.vm @@ -0,0 +1,153 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +#if(${prop.containmentInfo.containmentType}=="CONTAINER") +#set($opposite = ${prop.containmentInfo.opposite}) + /** + * Returns the value of the '${prop.name}' container reference. + * + * It is bidirectional and its opposite is '{@link ${prop.typeName}#${opposite.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @return the value of the '${prop.name}' container reference. + * @see ${type.fullTypeName}#set${prop.nameWithUpperCase}($prop.typeName) + */ +#elseif (${prop.containmentInfo.containmentType}=="CONTAINED") +#if(${prop.propType}=="COLLECTION") +#set($opposite = ${prop.containmentInfo.opposite}) + /** + * Returns the value of the '${prop.name}' containment list. + * + * It is bidirectional and its opposite is '{@link ${prop.genericTypeName}#${opposite.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @return the value of the '${prop.name}' containment list. + */ +#else ## if collection + /** + * Returns the value of the '${prop.name}' containment reference. + * + * It is bidirectional and its opposite is '{@link ${prop.typeName}#${prop.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @return the value of the '${prop.name}' containment reference. + * @see ${type.fullTypeName}#set${prop.nameWithUpperCase}($prop.typeName) + */ +#end## if collection +#elseif(${prop.isCrossRefProperty()})## ## if container / contained +#set($opposite = ${prop.referenceInfo.opposite}) +#if(${prop.propType}=="COLLECTION") ## if collection + /** + * Returns the value of the '${prop.name}' cross reference list. + * + * It is bidirectional and its opposite is '{@link ${prop.genericTypeName}#${opposite.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @return the value of the '${prop.name}' containment list. + */ +#else## ## if collection + /** + * Returns the value of the '${prop.name}' cross reference. + * + * It is bidirectional and its opposite is '{@link ${prop.typeName}#${prop.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @return the value of the '${prop.name}' cross reference. + * @see ${type.fullTypeName}#set${prop.nameWithUpperCase}($prop.typeName) + */ +#end## ## if collection +#elseif(${prop.propType}=="COLLECTION" )## ## if container / contained + /** + * Returns the value of the '${prop.name}' property. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @return the value of the '${prop.name}' property. + */ +#else## if collection + /** + * Returns the value of the '${prop.name}' property. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @return the value of the '${prop.name}' property. +#if(!$type.immutable) + * @see ${type.fullTypeName}#set${prop.nameWithUpperCase}($prop.typeName) +#end## if type is not immutable + */ +#end## if container / contained + $prop.typeNameForInterface ${prop.getterPrefix}${prop.nameWithUpperCase}(); diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/setter.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/setter.vm new file mode 100644 index 00000000..5854e388 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface/setter.vm @@ -0,0 +1,125 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +## we don't support setters for collection types +#if(${prop.propType}!="COLLECTION" && (${prop.getterOnly} == false || (${type.immutable} == false && ${type.interfaceOnly} == false) ) ) +## +#if(${prop.containmentInfo.containmentType}=="CONTAINER" && ${prop.containmentInfo.withoutOpposite} )## ## if container / contained +/** + * Sets the value of the '${prop.name}' container reference. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @param $prop.name the value to set + * @see ${type.fullTypeName}#get${prop.nameWithUpperCase}($prop.typeName) + */ + $prop.setterDeclaration; +#elseif(${prop.containmentInfo.containmentType}=="CONTAINER")## ## if container / contained +#set($opposite = ${prop.containmentInfo.opposite}) + /** + * Sets the value of the '${prop.name}' container reference. + * + * It is bidirectional and its opposite is '{@link ${prop.typeName}#${opposite.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @param $prop.name the value to set + * @see ${type.fullTypeName}#get${prop.nameWithUpperCase}($prop.typeName) + */ +#elseif (${prop.containmentInfo.containmentType}=="CONTAINED")## ## if container / contained + /** + * Sets the value of the '${prop.name}' containment reference. + * + * It is bidirectional and its opposite is '{@link ${prop.typeName}#${prop.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @param $prop.name the value to set + * @see ${type.fullTypeName}#${prop.getterPrefix}${prop.nameWithUpperCase}() + */ +#elseif(${prop.isCrossRefProperty()})## ## if container / contained +#set($opposite = ${prop.referenceInfo.opposite}) + /** + * Sets the value of the '${prop.name}' cross reference. + * + * It is bidirectional and its opposite is '{@link ${prop.typeName}#${prop.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @param $prop.name the value to set + * @see ${type.fullTypeName}#${prop.getterPrefix}${prop.nameWithUpperCase}() + */ +#else## ## if container / contained + /** + * Sets the value of the '${prop.name}' property. + * + * +#if(${prop.documented}) + *

${prop.customDocumentation}

+#else + * + * +#end + * + * + * @param $prop.name the value to set +#if(!$type.immutable) + * @see ${type.fullTypeName}#${prop.getterPrefix}${prop.nameWithUpperCase}() +#end## if type is not immutable + */ +#end## ## if container / contained + $prop.setterDeclaration; +#else## +// SKIPPING prop: ${prop.name} +// getter: ${prop.getterOnly} +// immutable: ${type.immutable} +// iface: ${type.interfaceOnly} +#end## diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface__vmf_type.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface__vmf_type.vm new file mode 100644 index 00000000..f7618127 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/interface__vmf_type.vm @@ -0,0 +1,59 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${type.implementation.packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// TODO see issue #9 import ${VCOLL_PKG}.*; + + +// interface + +// Internal Interface which gives access to impl features used in a 'multi-inheritance' context. +// Rationale: +// - we cannot cast to the implementation class to get access to impl features +// such as direct/raw property access since we simulate multiple inheritance +// - previously we just used reflection to circumvent the problem but this +// came at a huge performance cost +// - this interface supports multiple inheritance of impl features and +// gives access to proerties without reflection which results in a huge +// performance improvement (up to 10x) +interface __VMF_TYPE_${type.implementation.typeName} extends ${type.packageName}.${type.typeName}${type.vmfTypeIfaceImplementzString} { + +#foreach( $prop in ${type.implementation.properties}) + // --- PROP '$prop.typeName' + void __vmf_set_prop_${prop.name}($prop.typeName obj); + $prop.typeName __vmf_get_prop_${prop.name}(); +#if(${prop.crossRefProperty} && ${prop.propType} == "COLLECTION") + java.util.List<${type.packageName}.${prop.genericTypeName}> __vmf_get_prop_${prop.name}__vmf_RawList(); +#end## cross-ref collection +#end + + void _vmf_firePropertyChangeIfListenersArePresent( + String propertyName, Object oldValue, Object newValue + ); + +} \ No newline at end of file diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/read-only-implementation.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/read-only-implementation.vm new file mode 100644 index 00000000..33ea9e69 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/read-only-implementation.vm @@ -0,0 +1,308 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${type.readOnlyImplementation.packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal.*; +//import ${VCOLL_PKG}.*; +import ${type.packageName}.*; +//import java.beans.PropertyChangeListener; + +// property types imports +#foreach( $import in $type.implementation.imports ) +// import $import; +#end + +// interface + +/** + * An read-only representation of the model object {@code $type.fullTypeName}. + */ +@SuppressWarnings("deprecation") +class $type.readOnlyImplementation.typeName implements $type.readOnlyInterface.typeName, ${VMFPKG_INT}.VObjectInternal, VCloneableInternal { + + private final $type.typeName mutableObject; + + // Read-only view for collection properties + // - properties with collection type (model & non-model collections) + // - we don't allow/provide setters for collection properties +#foreach( $prop in $type.implementation.properties ) +#if($prop.propType == "COLLECTION") +#if($prop.genericType) + private ${VCOLL_PKG}.VList<${prop.genericType.readOnlyInterface.fullTypeName}> ${prop.name}; +#else + private ${VCOLL_PKG}.VList<${prop.genericPackageName}.${prop.genericTypeName}> ${prop.name}; +#end ## if genericType +#end ## if collection +#end ## for each property + + public ${type.readOnlyImplementation.typeName}($type.typeName mutableObject) { + this.mutableObject = mutableObject; + } + +#foreach( $prop in $type.implementation.properties ) + + @Override +#if($prop.propType == "COLLECTION") +#if($prop.genericType) + // generic type is a model-type + public ${VCOLL_PKG}.VList<${prop.genericType.readOnlyInterface.fullTypeName}> ${prop.getterPrefix}${prop.nameWithUpperCase}() { + + // we return an unmodifiable mapped list that contains read-only versions of the list elements + // since read-only types and normal types are incompatible by design, we specify the lambda + // operation that converts an element into a read-only version of that element + if(this.${prop.name} == null) { + this.${prop.name} = ${VCOLL_PKG}.VMappedList.newUnmodifiableInstance(mutableObject.${prop.getterPrefix}${prop.nameWithUpperCase}(), (e)->e.asReadOnly()); + } + + return this.${prop.name}; + +#else + public ${VCOLL_PKG}.VList<${prop.genericPackageName}.${prop.genericTypeName}> ${prop.getterPrefix}${prop.nameWithUpperCase}() { + + if(this.${prop.name} == null) { + this.${prop.name} = this.mutableObject.${prop.getterPrefix}${prop.nameWithUpperCase}(); + } + + return this.${prop.name}; +#end ## if generic type + +#elseif(${prop.type}) +#if($prop.type.immutable) + // property type is a model-type + public $prop.type.typeName ${prop.getterPrefix}${prop.nameWithUpperCase}() { + if(this.mutableObject.${prop.getterPrefix}${prop.nameWithUpperCase}()!=null) { + return this.mutableObject.${prop.getterPrefix}${prop.nameWithUpperCase}(); + } else { + return null; + } +#else## if prop type is immutable + // property type is a model-type + public $prop.type.readOnlyInterface.typeName ${prop.getterPrefix}${prop.nameWithUpperCase}() { + if(this.mutableObject.${prop.getterPrefix}${prop.nameWithUpperCase}()!=null) { + return this.mutableObject.${prop.getterPrefix}${prop.nameWithUpperCase}().asReadOnly(); + } else { + return null; + } +#end## if prop type is immutable +#else + public $prop.typeName ${prop.getterPrefix}${prop.nameWithUpperCase}() { + return this.mutableObject.${prop.getterPrefix}${prop.nameWithUpperCase}(); +#end + } + +#end // end for each property + + @Override + public void addPropertyChangeListener(java.beans.PropertyChangeListener l) { + ((${VMFPKG_INT}.VObjectInternal)this.mutableObject).addPropertyChangeListener(l); + } + + @Override + public void removePropertyChangeListener(java.beans.PropertyChangeListener l) { + ((${VMFPKG_INT}.VObjectInternal)this.mutableObject).removePropertyChangeListener(l); + } + + @Override + public String toString() { + return this.mutableObject.toString(); + } + + @Override + public void __vmf_toString(StringBuilder sb, java.util.IdentityHashMap identityMap) { + ((${VMFPKG_INT}.VObjectInternal)this.mutableObject).__vmf_toString(sb, identityMap); + } + + @Override + public boolean equals(Object o) { + return this.mutableObject.equals(o); + } + + @Override + public int hashCode() { + return this.mutableObject.hashCode(); + } + + @Override + public boolean _vmf_equals(Object o) { + return ((${VMFPKG_INT}.VObjectInternal)this.mutableObject)._vmf_equals(o); + } + + @Override + public int _vmf_hashCode() { + return ((${VMFPKG_INT}.VObjectInternal)this.mutableObject)._vmf_hashCode(); + } + + @Override + public $type.typeName _vmf_getMutableObject() { + return this.mutableObject; + } + + @Override + public $type.readOnlyImplementation.typeName asReadOnly() { + return this; + } + + // -------------------------------------------------------------------- + // --- Cloning + // -------------------------------------------------------------------- + + @Override + public ${type.readOnlyInterface.typeName} clone() { + return this.mutableObject.clone().asReadOnly(); + } + + @Override + public ${type.typeName} asModifiable() { + return this.mutableObject.clone(); + } + + @Override + public ${type.typeName} _vmf_deepCopy( + java.util.IdentityHashMap identityMap) { + return (${type.typeName}) + ((VCloneableInternal)this.mutableObject)._vmf_deepCopy( + new java.util.IdentityHashMap<>()); + } + + @Override + public ${type.readOnlyInterface.typeName} _vmf_shallowCopy( + java.util.IdentityHashMap identityMap) { + return (${type.readOnlyInterface.typeName}) + ((VCloneableInternal)this.mutableObject)._vmf_shallowCopy( + new java.util.IdentityHashMap<>()).asReadOnly(); + } + + @Override + public void _vmf_setThreadLocalEquals(ThreadLocal> threadlocalMap) { + ((${VMFPKG_INT}.VObjectInternal)this.mutableObject)._vmf_setThreadLocalEquals(threadlocalMap); + } + + // -------------------------------------------------------------------- + // --- Public VMF API + // -------------------------------------------------------------------- + + @Override + public ${VMFPKG}.VMF vmf() { + return new ${VMFPKG}.VMF() { + public ${VMFPKG}.Content content() { + return new ${VMFPKG}.Content() { + public ${VMFPKG}.VIterator iterator() { + return ${VMFPKG}.VIterator.of(${type.readOnlyImplementation.typeName}.this); + } + public java.util.stream.Stream<${VMFPKG}.VObject> stream() { + return ${VMFPKG}.VIterator.of(${type.readOnlyImplementation.typeName}.this).asStream(); + } + + public ${VMFPKG}.VIterator iterator(${VMFPKG}.VIterator.IterationStrategy strategy) { + return ${VMFPKG}.VIterator.of(${type.readOnlyImplementation.typeName}.this, strategy); + } + public java.util.stream.Stream<${VMFPKG}.VObject> stream(${VMFPKG}.VIterator.IterationStrategy strategy) { + return ${VMFPKG}.VIterator.of(${type.readOnlyImplementation.typeName}.this, strategy).asStream(); + } + public java.util.stream.Stream stream(Class type) { + return stream().filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e); + } + public java.util.stream.Stream stream(Class type, ${VMFPKG}.VIterator.IterationStrategy strategy) { + return stream(strategy).filter(e->type.isAssignableFrom(e.getClass())).map(e->(T)e); + } + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> referencedBy() { + return _vmf_referencedBy().asUnmodifiable(); + } + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> references() { + return _vmf_references().asUnmodifiable(); + } + + @Override + public ${type.readOnlyInterface.typeName} deepCopy() { + return (${type.readOnlyImplementation.typeName}) + ((VCloneableInternal)${type.readOnlyImplementation.typeName}.this.mutableObject)._vmf_deepCopy( + new java.util.IdentityHashMap<>()).asReadOnly(); + } + + @Override + public ${type.readOnlyInterface.typeName} shallowCopy() { + return ${type.readOnlyImplementation.typeName}. + this._vmf_shallowCopy(new java.util.IdentityHashMap<>()); + } + }; + } + + private ${VMFPKG_INT}.ReflectImpl reflect; + + public ${VMFPKG}.Reflect reflect() { + if (reflect==null) { + reflect = new ${VMFPKG_INT}.ReflectImpl(); + reflect.setModel(${type.readOnlyImplementation.typeName}.this); + } + + return reflect; + } + }; // end vmf + } + + + // -------------------------------------------------------------------- + // --- Reflection methods + // -------------------------------------------------------------------- + + // type id for improved reflection performance + public static final int _VMF_TYPE_ID = $type.readOnlyImplementation.typeId; + + @Override + public int _vmf_getTypeId() { + return _VMF_TYPE_ID; + } + + // Type info + @Override + public ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.Type _vmf_getType() { + return ${type.packageName}.${type.typeName}.type(); + } + +#set($readOnlyVal=true) +#parse("${VMF_TEMPLATE_PATH}reflection/reflection.vm") + + @Override + public boolean _vmf_isReadOnly() { + return true; + } + + // -------------------------------------------------------------------- + // --- Id related methods + // -------------------------------------------------------------------- + + // id management is currently not part of VMF (TODO how should we support this?) + + // -------------------------------------------------------------------- + // --- Reference methods + // -------------------------------------------------------------------- + + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> _vmf_referencedBy() { return ((${VMFPKG_INT}.VObjectInternalModifiable)this.mutableObject)._vmf_referencedBy();} + + public ${VCOLL_PKG}.VList<${VMFPKG}.VObject> _vmf_references() { return ((${VMFPKG_INT}.VObjectInternalModifiable)this.mutableObject)._vmf_references();} +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/read-only-interface.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/read-only-interface.vm new file mode 100644 index 00000000..712d3176 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/read-only-interface.vm @@ -0,0 +1,141 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${type.packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// import ${VCOLL_PKG}.*; + +// property types imports +#foreach( $import in $type.imports ) +// import $import; +#end + +// interface + +/** + * An read-only representation of the model object {@code $type.fullTypeName}. + * + * +#if(${type.documented}) + *

${type.customDocumentation}

+#else + * + * +#end + * + */ +public interface $type.readOnlyInterface.typeName extends ${VMFPKG}.VObject$type.readOnlyImplementsString, ${VMFPKG}.ReadOnly #if($type.interfaceOnlyWithGettersOnly && $type.allPropertyTypesAreInterfaceOnlyWithGettersOnlyOrImmutable()), $type.typeName #end{ +#foreach( $prop in $type.properties ) + +#if(${prop.containmentInfo.containmentType}=="CONTAINER") +#set($opposite = ${prop.containmentInfo.opposite}) +/** + * Returns the value of the '${prop.name}' container reference. + * + * It is bidirectional and its opposite is '{@link ${opposite.parent.readOnlyInterface.typeName}#${prop.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * + * + * + * @return the value of the '${prop.name}' container reference. + * @see ${type.fullTypeName}#\set${prop.nameWithUpperCase}($prop.typeName) + */ +#elseif (${prop.containmentInfo.containmentType}=="CONTAINED") +#if(${prop.propType}=="COLLECTION") +#set($opposite = ${prop.containmentInfo.opposite}) + /** + * Returns the value of the '${prop.name}' containment list. + * + * It is bidirectional and its opposite is '{@link ${prop.genericType.readOnlyInterface.typeName}#${prop.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * + * + * + * @return the value of the '${prop.name}' containment list. + */ +#else ## if collection +#set($opposite = ${prop.containmentInfo.opposite}) + /** + * Returns the value of the '${prop.name}' containment reference. + * + * It is bidirectional and its opposite is '{@link ${prop.type.readOnlyInterface.typeName}#${prop.getterPrefix}${opposite.nameWithUpperCase}() ${opposite.name}}'. + * + * + * + * + * @return the value of the '${prop.name}' containment reference. + * @see ${type.fullTypeName}#\set${prop.nameWithUpperCase}($prop.typeName) + */ +#end ## if collection +#else ## if container / contained + /** + * Returns the value of the '${prop.name}' property. + * + * + * + * + * @return the value of the '${prop.name}' property. + * #if(${prop.propType}!="COLLECTION")@see ${type.fullTypeName}#\set${prop.nameWithUpperCase}($prop.typeName) +#end + */ +#end ## if container / contained +#if($prop.propType == "COLLECTION") +#if($prop.genericType) + // generic model type + public ${VCOLL_PKG}.VList<${prop.genericType.readOnlyInterface.fullTypeName}> ${prop.getterPrefix}${prop.nameWithUpperCase}(); +// public java.util.List<${prop.genericType.readOnlyInterface.fullTypeName}> ${prop.getterPrefix}${prop.nameWithUpperCase}(); +#else + public ${VCOLL_PKG}.VList<${prop.genericPackageName}.${prop.genericTypeName}> ${prop.getterPrefix}${prop.nameWithUpperCase}(); +// public java.util.List<${prop.genericPackageName}.${prop.genericTypeName}> ${prop.getterPrefix}${prop.nameWithUpperCase}(); +#end ## if genericType +#else + public #if($prop.type)#if($prop.type.immutable)$prop.type.typeName#else$prop.type.readOnlyInterface.typeName#end#else$prop.typeName#end ${prop.getterPrefix}${prop.nameWithUpperCase}(); +#end ## if collection + +#end ## for each + + /** + * Returns a deep clone of this object. + * @return a deep clone of this object + */ + @Override + public ${type.readOnlyInterface.typeName} clone(); + + @Override + default ${type.readOnlyInterface.typeName} asReadOnly() { + return this; + } + +#if(!${type.isInterfaceOnly()}) + /** + * Returns a modifiable deep clone of this object. + * @return a modifiable deep clone of this object + */ + ${type.typeName} asModifiable(); +#end## if type is not interface-only type + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/reflection/reflection-read-only.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/reflection/reflection-read-only.vm new file mode 100644 index 00000000..20e60f8c --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/reflection/reflection-read-only.vm @@ -0,0 +1,56 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +## CURRENTLY NOT USED +## might reduce memory overhead, since currently, we have implementations in +## writable and read-only impl + + @Override + public String[] _vmf_getPropertyNames() { + return this.mutableObject._vmf_propertyNames; + } + + @Override + public int[] _vmf_getPropertyTypes() { + return this.mutableObject._vmf_propertyTypes; + } + + @Override + public int[] _vmf_getPropertyTypeNames() { + return _VMF_PROPERTY_TYPE_NAMES; + } + + @Override + public int[] _vmf_getIndicesOfPropertiesWithModelTypes() { + return this.mutableObject._vmf_propertiesWithModelTypesIndices; + } + + @Override + public Object getPropertyValueById(int propertyId) { + return this.mutableObject.getPropertyValueById(propertyId); + } + + @Override + public int[] _vmf_getChildrenIndices() { + return _VMF_CHILDREN_INDICES; + } diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/reflection/reflection.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/reflection/reflection.vm new file mode 100644 index 00000000..473934c0 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/reflection/reflection.vm @@ -0,0 +1,302 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# + static final String[] _VMF_SUPER_TYPE_NAMES = { +#foreach($tName in $type.implementz) "$tName.fullTypeName"#if($foreach.hasNext),#end$newline#end + }; + + @Override + public String[] _vmf_getSuperTypeNames() { + return _VMF_SUPER_TYPE_NAMES; + } + + static final String[] _VMF_PROPERTY_NAMES = { +#foreach($prop in $type.implementation.properties) "$prop.name"#if($foreach.hasNext),#end$newline#end + }; + + static final String[] _VMF_PROPERTY_TYPE_NAMES = { +#foreach($prop in $type.implementation.properties) + "$prop.typeName"#if($foreach.hasNext),#else #end // type id $prop.typeId +#end + }; + + static final int[] _VMF_PROPERTY_TYPES = { +#foreach($prop in $type.implementation.properties) + ${StringUtil.alignRight($prop.typeId, 5)}#if($foreach.hasNext),#else #end // type $prop.typeName +#end + }; + + + /** + * - indices of model objects as properties + * - parents, i.e., containers are skipped + * - only indices of reference properties and contained elements, i.e., + * children are listed here + */ + static final int[] _VMF_PROPERTIES_WITH_MODEL_TYPES_INDICES = { +#foreach($prop in $type.implementation.properties) +#if($prop.type&&$prop.containmentInfo.containmentType!="CONTAINER") ${StringUtil.alignRight($foreach.index, 5)}#if($foreach.hasNext),#else #end // type $prop.typeName$newline#end +#end + }; + + /** + * - indices of lists that contain model objects as elements + */ + static final int[] _VMF_PROPERTIES_WITH_MODEL_ELEMENT_TYPES_INDICES = { +#foreach($prop in $type.implementation.properties) +#if($prop.genericType) ${StringUtil.alignRight($foreach.index, 5)}#if($foreach.hasNext),#else #end // type $prop.typeName$newline#end +#end + }; + + /** + * - indices of model objects as properties and model objects as + * elements of lists + * - parents, i.e., containers are skipped + * - only indices of reference properties and contained elements, i.e., + * children are listed here + */ + static final int[] _VMF_PROPERTIES_WITH_MODEL_TYPE_OR_ELEMENT_TYPES_INDICES = { +#foreach($prop in $type.implementation.properties) +#if(($prop.type||$prop.genericType)&&$prop.containmentInfo.containmentType!="CONTAINER") ${StringUtil.alignRight($foreach.index, 5)}#if($foreach.hasNext),#else #end // type $prop.typeName$newline#end +#end + }; + + /** + * - indices of model children + * - parents, i.e., containers and pure references are skipped + * - only indices of contained elements, i.e., + * children are listed here + */ + static final int[] _VMF_CHILDREN_INDICES = { +#foreach($prop in $type.implementation.properties) +#if(($prop.type||$prop.genericType)&&$prop.containmentInfo.containmentType=="CONTAINED") ${StringUtil.alignRight($foreach.index, 5)}#if($foreach.hasNext),#else #end // type $prop.typeName$newline#end +#end + }; + + /** + * - indices of model parents + * - children, i.e., contained elements and pure references are skipped + * - only indices of container/parent elements, i.e., + * children are listed here + */ + static final int[] _VMF_PARENT_INDICES = { +#foreach($prop in $type.implementation.properties) +#if($prop.type && $prop.containmentInfo.containmentType=="CONTAINER") ${StringUtil.alignRight($foreach.index, 5)}#if($foreach.hasNext),#else #end // type $prop.typeName$newline#end +#end + }; + + @Override + public String[] _vmf_getPropertyNames() { + return _VMF_PROPERTY_NAMES; + } + + @Override + public int[] _vmf_getPropertyTypes() { + return _VMF_PROPERTY_TYPES; + } + + @Override + public String[] _vmf_getPropertyTypeNames() { + return _VMF_PROPERTY_TYPE_NAMES; + } + + @Override + public int[] _vmf_getIndicesOfPropertiesWithModelTypes() { + return _VMF_PROPERTIES_WITH_MODEL_TYPES_INDICES; + } + + @Override + public int[] _vmf_getIndicesOfPropertiesWithModelElementTypes() { + return _VMF_PROPERTIES_WITH_MODEL_ELEMENT_TYPES_INDICES; + } + + @Override + public int[] _vmf_getIndicesOfPropertiesWithModelTypeOrElementTypes() { + return _VMF_PROPERTIES_WITH_MODEL_TYPE_OR_ELEMENT_TYPES_INDICES; + } + + @Override + public int[] _vmf_getChildrenIndices() { + return _VMF_CHILDREN_INDICES; + } + + @Override + public int[] _vmf_getParentIndices() { + return _VMF_PARENT_INDICES; + } + + @Override + public Object _vmf_getPropertyValueById(int propertyId) { + + switch(propertyId) { +#foreach($prop in $type.implementation.properties) + case $foreach.index: + // TODO check whether we can prevent lazy initialized properties from + // being initialized just for iterating the object graph + return ${prop.getterPrefix}${prop.nameWithUpperCase}(); +#end## for-each property + } + + return null; + } + + @Override + public int _vmf_getPropertyIdByName(String propertyName) { + switch(propertyName) { +#foreach($prop in $type.implementation.properties) + case "$prop.name": + return $foreach.index; +#end## for-each property + default: + return -1; + } // end switch + } + +#if(!$readOnlyVal) + @Override + public void _vmf_setPropertyValueById(int propertyId, Object value) { + switch(propertyId) { +#foreach($prop in $type.implementation.properties) +#if(!$prop.genericType) +#if(${prop.propType}!="COLLECTION") ## && $prop.containmentInfo.containmentType!="CONTAINER" + case $foreach.index: // normal property (no collection) + set${prop.nameWithUpperCase}((${prop.typeName})value); + break; +#elseif(${prop.propType}=="COLLECTION") + case $foreach.index: // collection property + get${prop.nameWithUpperCase}().clear(); + get${prop.nameWithUpperCase}().addAll((${prop.typeName})value); + break; +#end## end if !collection +#end## end if !genericType +#end## for-each property + default: + throw new RuntimeException("Cannot set property with id="+propertyId +": property is not writable."); + } // end switch + } +#end## if !readOnlyVal + + @Override + public Object _vmf_getDefaultValueById(int propertyId) { + + switch(propertyId) { +#foreach($prop in $type.implementation.properties) + case $foreach.index: + Object __vmf_default_value_tmp$prop.nameWithUpperCase = _VMF_DEFAULT_VALUES[$prop.getPropId()]; +#if(${prop.propType}=="PRIMITIVE")## if prop is primitive + if(__vmf_default_value_tmp$prop.nameWithUpperCase==null) { + return +#if(${prop.getDefaultValueAsString()}=="null")## if default is null + #if(${prop.typeName}=="boolean")false#else 0#end; +#else## if default is null + ${prop.getDefaultValueAsString()}; +#end## if default is null + } else { + return __vmf_default_value_tmp$prop.nameWithUpperCase; + } +#else## if prop is primitive + if(__vmf_default_value_tmp$prop.nameWithUpperCase==null) { + return ${prop.getDefaultValueAsString()}; + } else { + return __vmf_default_value_tmp$prop.nameWithUpperCase; + } +#end## if prop is primitive + +#end## for-each property + } // end switch + + return null; + } + + @Override + public void _vmf_setDefaultValueById(int propertyId, Object defaultValue) { + +#foreach($prop in $type.implementation.properties) +#if(${prop.containmentProperty}) + // property ${prop.name} + if(propertyId == $foreach.index) { + throw new RuntimeException("Cannot set default value for property '${prop.name}' with id="+propertyId +": property is a containment property and not writable."); + } +#end## if is containment +#end##for each property + +#if(!$readOnlyVal) + // if the value was previously unset then we need to update + // the value to the new default value + boolean isSetBeforeDefaultUpdate = _vmf_isSetById(propertyId); + _VMF_DEFAULT_VALUES[propertyId] = defaultValue; + if(!isSetBeforeDefaultUpdate) { + _vmf_unsetById(propertyId); + } +#end## if !readOnlyVal + } + + @Override + public boolean _vmf_isSetById(int propertyId) { + return !java.util.Objects.equals(_vmf_getDefaultValueById(propertyId), _vmf_getPropertyValueById(propertyId)); + } + +#if(!$readOnlyVal) + @Override + public void _vmf_unsetById(int propertyId) { + _vmf_setPropertyValueById(propertyId, _vmf_getDefaultValueById(propertyId)); + } +#end## if !readOnlyVal + + final Object[] _VMF_DEFAULT_VALUES = { +#foreach($prop in $type.implementation.properties) + null#if($foreach.hasNext),#else #end // type ${prop.name} #if(${prop.containmentProperty})(containment type, no defaut value possible)#end + +#end## for each property + }; + + // ------ ANNOTATIONS ------ + + final static ${VMFPKG}.Annotation[] _VMF_OBJECT_ANNOTATIONS = { +#foreach($annotation in $type.implementation.annotations) + new ${VMFPKG}.internal.AnnotationImpl("$StringUtil.escapeJavaStyleString($annotation.key, false)","$StringUtil.escapeJavaStyleString($annotation.value, false)")#if($foreach.hasNext),#else #end + +#end## for each pannotationroperty + }; + + final static ${VMFPKG}.Annotation[][] _VMF_PROPERTY_ANNOTATIONS = { +#foreach($prop in $type.implementation.properties) + { +#foreach($annotation in $prop.annotations) + new ${VMFPKG}.internal.AnnotationImpl("$StringUtil.escapeJavaStyleString($annotation.key, false)","$StringUtil.escapeJavaStyleString($annotation.value, false)")#if($foreach.hasNext),#else #end + +#end## for each annotation + }#if($foreach.hasNext),#else #end + +#end## for each property + }; + + @Override + public java.util.List<${VMFPKG}.Annotation> _vmf_getPropertyAnnotationsById(int propertyId) { + return java.util.Arrays.asList(_VMF_PROPERTY_ANNOTATIONS[propertyId]); + } + + @Override + public java.util.List<${VMFPKG}.Annotation> _vmf_getAnnotations() { + return java.util.Arrays.asList(_VMF_OBJECT_ANNOTATIONS); + } diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-switch-interface.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-switch-interface.vm new file mode 100644 index 00000000..f7d2030f --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-switch-interface.vm @@ -0,0 +1,66 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal.*; + + +public interface SwitchFor${modelSwitchName}Model { + + @SuppressWarnings("deprecation") + default T doSwitch(${VMFPKG}.VObject o) { + T result = null; + switch(((${VMFPKG_INT}.VObjectInternal)o)._vmf_getTypeId()) { +#foreach($type in $model.types) + #set($modifiableIdx = $foreach.index*2 + 0) + #set($readOnlyIdx = $foreach.index*2 + 1) + case $modifiableIdx: + // TODO check whether we can prevent lazy initialized properties from + // being initialized just for iterating the object graph + result = case${type.typeName}(($type.typeName) o); + return result == null?defaultValue(o):result; +#end## for-each type + default: + return defaultValue(o); + } + } // end doSwitch() + + /** + * Default value that will be return if the matching case method returns {@code null}. + * @return default value + */ + default T defaultValue(${VMFPKG}.VObject o) { + return null; + } + +#foreach($type in $model.types) + + default T case${type.typeName}($type.typeName object) {return null;} +#end## for-each type + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-switch-read-only-interface.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-switch-read-only-interface.vm new file mode 100644 index 00000000..97405fed --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-switch-read-only-interface.vm @@ -0,0 +1,66 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal.*; + + +public interface ReadOnlySwitchFor${modelSwitchName}Model { + + @SuppressWarnings("deprecation") + default T doSwitch(${VMFPKG}.VObject o) { + T result = null; + switch(((${VMFPKG_INT}.VObjectInternal)o)._vmf_getTypeId()) { +#foreach($type in $model.types) + #set($modifiableIdx = $foreach.index*2 + 0) + #set($readOnlyIdx = $foreach.index*2 + 1) + case $readOnlyIdx: + // TODO check whether we can prevent lazy initialized properties from + // being initialized just for iterating the object graph + result = case${type.readOnlyInterface.typeName}((${type.readOnlyInterface.typeName}) o); + return result == null?defaultValue(o):result; +#end ## for-each type + default: + return defaultValue(o); + } + } // end doSwitch() + + /** + * Default value that will be return if the matching case method returns {code null}. + * @return default value + */ + default T defaultValue(${VMFPKG}.VObject o) { + return null; + } + +#foreach($type in $model.types) + + default T case${type.readOnlyInterface.typeName}(${type.readOnlyInterface.typeName} object) {return null;} +#end ## for-each type + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-traversal-listener-interface.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-traversal-listener-interface.vm new file mode 100644 index 00000000..c93c3270 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-traversal-listener-interface.vm @@ -0,0 +1,72 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal.*; + +public interface ListenerFor${modelSwitchName}Model extends ${VMFPKG}.TraversalListener { + + @SuppressWarnings("deprecation") + @Override + default void onEnter(${VMFPKG}.VObject o) { + switch(((${VMFPKG_INT}.VObjectInternal)o)._vmf_getTypeId()) { +#foreach($type in $model.types) + #set($modifiableIdx = $foreach.index*2 + 0) + #set($readOnlyIdx = $foreach.index*2 + 1) + case $modifiableIdx: + // TODO check whether we can prevent lazy initialized properties from + // being initialized just for iterating the object graph + onEnter${type.typeName}(($type.typeName) o); + break; +#end## for-each type + } + } // end onEnter() + + @SuppressWarnings("deprecation") + @Override + default void onExit(${VMFPKG}.VObject o) { + switch(((${VMFPKG_INT}.VObjectInternal)o)._vmf_getTypeId()) { +#foreach($type in $model.types) + #set($modifiableIdx = $foreach.index*2 + 0) + #set($readOnlyIdx = $foreach.index*2 + 1) + case $modifiableIdx: + // TODO check whether we can prevent lazy initialized properties from + // being initialized just for iterating the object graph + onExit${type.typeName}(($type.typeName) o); + break; +#end## for-each type + } + } // end onEnter() + +#foreach($type in $model.types) + + default void onEnter${type.typeName}($type.typeName object) {} + default void onExit${type.typeName}($type.typeName object) {} +#end## for-each type + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-traversal-listener-read-only-interface.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-traversal-listener-read-only-interface.vm new file mode 100644 index 00000000..ee24f8d0 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-traversal-listener-read-only-interface.vm @@ -0,0 +1,72 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; +// import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal.*; + +public interface ReadOnlyListenerFor${modelSwitchName}Model extends ${VMFPKG}.TraversalListener { + + @SuppressWarnings("deprecation") + @Override + default void onEnter(${VMFPKG}.VObject o) { + switch(((${VMFPKG_INT}.VObjectInternal)o)._vmf_getTypeId()) { +#foreach($type in $model.types) + #set($modifiableIdx = $foreach.index*2 + 0) + #set($readOnlyIdx = $foreach.index*2 + 1) + case $modifiableIdx: + // TODO check whether we can prevent lazy initialized properties from + // being initialized just for iterating the object graph + onEnter${type.readOnlyInterface.typeName}((${type.readOnlyInterface.typeName}) o); + break; +#end## for-each type + } + } // end onEnter() + + @SuppressWarnings("deprecation") + @Override + default void onExit(${VMFPKG}.VObject o) { + switch(((${VMFPKG_INT}.VObjectInternal)o)._vmf_getTypeId()) { +#foreach($type in $model.types) + #set($modifiableIdx = $foreach.index*2 + 0) + #set($readOnlyIdx = $foreach.index*2 + 1) + case $modifiableIdx: + // TODO check whether we can prevent lazy initialized properties from + // being initialized just for iterating the object graph + onExit${type.readOnlyInterface.typeName}((${type.readOnlyInterface.typeName}) o); + break; +#end## for-each type + } + } // end onEnter() + +#foreach($type in $model.types) + + default void onEnter${type.readOnlyInterface.typeName}(${type.readOnlyInterface.typeName} object) {} + default void onExit${type.readOnlyInterface.typeName}(${type.readOnlyInterface.typeName} object) {} +#end## for-each type + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-walker-implementation.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-walker-implementation.vm new file mode 100644 index 00000000..e08402c0 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-model-walker-implementation.vm @@ -0,0 +1,34 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +## package ${packageName}; +## +## // vmf imports +## import ${VMF_CORE_API_PKG}.${VMF_VMFUTIL_PKG_EXT}.*; +## +## +## public class ModelWalker { +## #foreach($type in $model.types) +## T visit${type.typeName}($type.typeName object); +## #end ## for-each type +## } diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-vcloneable-internal.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-vcloneable-internal.vm new file mode 100644 index 00000000..744d5af6 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-vcloneable-internal.vm @@ -0,0 +1,53 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; + +// property types imports +#foreach( $import in $type.imports ) +import $import; +#end + +// interface + +/** + * A representation of the model object {@code $type.fullTypeName}. + */ +interface VCloneableInternal { + + /** + * Performs a deep copy (takes care of references and cycles). + */ + ${VMFPKG}.VObject _vmf_deepCopy(java.util.IdentityHashMap identityMap); + + /** + * Performs a shallow copy (takes care of references and cycles). + */ + ${VMFPKG}.VObject _vmf_shallowCopy(java.util.IdentityHashMap identityMap); + +} diff --git a/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-vobject-internal.vm b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-vobject-internal.vm new file mode 100644 index 00000000..2fe378e1 --- /dev/null +++ b/core/out/production/resources/eu/mihosoft/vmf/vmtemplates/vmf-vobject-internal.vm @@ -0,0 +1,80 @@ +#* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + *# +package ${packageName}; + +// vmf imports +#set($VMFPKG="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}") +#set($VMFPKG_INT="${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.internal") +//import ${VMF_RUNTIME_API_PKG}.${VMF_CORE_PKG_EXT}.*; + +// property types imports +#foreach( $import in $type.imports ) +import $import; +#end + +// interface + +/** + * Internal interface. Don't rely on this API. + */ +interface VObjectInternal extends ${VMFPKG}.VObject { + + /** + * Returns the type id of this class. + */ + int _vmf_getTypeId(); + + /** + * Returns the names of the properties defined in this type/object. + */ + public String[] _vmf_getPropertyNames(); + + /** + * Returns the types of the properties defined in this type/object. + */ + public int[] _vmf_getPropertyTypes(); + + /** + * Returns values of properties by id (calls getter methods). + */ + public Object _vmf_getPropertyValueById(int propertyId); + + /** + * Returns the indices of all properties with model types or collections + * that contain model instances. + */ + public int[] _vmf_getIndicesOfPropertiesWithModelTypes(); + + /** + * Returns the indices of all collection properties with model element types. + */ + public int[] _vmf_getIndicesOfPropertiesWithModelElementTypes(); + + /** + * Returns the indices of all collection properties with model element types + * or collections that contain model instances. + */ + public int[] _vmf_getIndicesOfPropertiesWithModelTypeOrElementTypes(); + +} diff --git a/core/out/test/classes/eu/mihosoft/vmf/VMFTest.class b/core/out/test/classes/eu/mihosoft/vmf/VMFTest.class new file mode 100644 index 00000000..d847a17c Binary files /dev/null and b/core/out/test/classes/eu/mihosoft/vmf/VMFTest.class differ diff --git a/core/out/test/classes/eu/mihosoft/vmf/core/ModelTest.class b/core/out/test/classes/eu/mihosoft/vmf/core/ModelTest.class new file mode 100644 index 00000000..c328e930 Binary files /dev/null and b/core/out/test/classes/eu/mihosoft/vmf/core/ModelTest.class differ diff --git a/core/out/test/classes/eu/mihosoft/vmf/testmodels/invalid/ModelInInvalidPackage.class b/core/out/test/classes/eu/mihosoft/vmf/testmodels/invalid/ModelInInvalidPackage.class new file mode 100644 index 00000000..9372d80c Binary files /dev/null and b/core/out/test/classes/eu/mihosoft/vmf/testmodels/invalid/ModelInInvalidPackage.class differ diff --git a/core/out/test/classes/eu/mihosoft/vmf/testmodels/invalidclassesmodel/vmfmodel/ModelInvalidClasses.class b/core/out/test/classes/eu/mihosoft/vmf/testmodels/invalidclassesmodel/vmfmodel/ModelInvalidClasses.class new file mode 100644 index 00000000..e5a7da02 Binary files /dev/null and b/core/out/test/classes/eu/mihosoft/vmf/testmodels/invalidclassesmodel/vmfmodel/ModelInvalidClasses.class differ diff --git a/core/out/test/classes/eu/mihosoft/vmf/testmodels/vmfmodel/ModelInValidPackage.class b/core/out/test/classes/eu/mihosoft/vmf/testmodels/vmfmodel/ModelInValidPackage.class new file mode 100644 index 00000000..1c77ef35 Binary files /dev/null and b/core/out/test/classes/eu/mihosoft/vmf/testmodels/vmfmodel/ModelInValidPackage.class differ diff --git a/runtime/build.gradle b/runtime/build.gradle index 54e15fdf..816d6b36 100644 --- a/runtime/build.gradle +++ b/runtime/build.gradle @@ -45,6 +45,8 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compile group: 'eu.mihosoft.vcollections', name: 'vcollections', version: '0.3.3' compile group: 'eu.mihosoft.vcollections', name: 'vcollections', version: '0.3.3', classifier: 'sources' + compile files ('libs/apted-master.jar') + implementation 'eu.mihosoft.ext.apted:apted:0.1' } jar { diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/Diffing.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/Diffing.java new file mode 100644 index 00000000..a2830db1 --- /dev/null +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/Diffing.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ +package eu.mihosoft.vmf.runtime.core; + +import java.util.List; + +/** + * Diffing feature for the object graph. Can be accessed via the {@code vmf()} method: + * + *

+ * VObject o = ...
+ * Diffing r = o.vmf().diffing()
+ * 
+ * + * @author Michael Hoffer (info@michaelhoffer.de) + * @author Paul Zügel + * @see {@link VMF} + */ + +public interface Diffing { + + /** + * Initializes diffing function. + * @param targetObj the target object to which the source object is compared + */ + void init(VObject targetObj); + + /** + * Setting the source object + * @param source the source object + */ + void setSource(VObject source); + + /** + * Prints out step by step changes onto the console + */ + void printChanges(); + + /** + * Applies changes onto the source object + * @return returns if changes successful + */ + boolean applyChanges(); + + /** + * Returns a list of changes to transform the source object into the target object + * @return list of changes + */ + List getChanges(); +} diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/VMF.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/VMF.java index a17fbe5a..da102258 100644 --- a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/VMF.java +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/VMF.java @@ -39,7 +39,15 @@ * @see {@link Reflect} */ public interface VMF { - + /** + * Returns the diffing feature for this object. + * @return the diffing feature for this object. + */ + default Diffing diffing() { + this.diffing().setSource((VObject) this); + throw new UnsupportedOperationException("FIXME: unsupported method invoked. This should not happen :("); + } + /** * Returns the content of this object. * @return the content of this object diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/VMFUtil.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/VMFUtil.java new file mode 100644 index 00000000..48ec6e95 --- /dev/null +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/VMFUtil.java @@ -0,0 +1,84 @@ +package eu.mihosoft.vmf.runtime.core; + +import java.lang.reflect.InvocationTargetException; + +import eu.mihosoft.vmf.runtime.core.Type; +import eu.mihosoft.vmf.runtime.core.VObject; + +/** + * Utility interface that contains methods for instantiating VObjects + * reflectively. This functionality hasn't been added to VMF yet. Expect this + * API to vanish once VMF has an improved reflection API. + */ +public interface VMFUtil { + + /** + * Returns the type if the specified object. + * @param object object + * @return type of the specified object + */ + public static Type getType(VObject object) { + try { + + String packageName = object.getClass().getPackage().getName(); + packageName = packageName.substring(0, packageName.length() - ".impl".length()); + String className = object.getClass().getSimpleName(); + className = className.substring(0, className.length() - "Impl".length()); + + Type type = (Type) Class.forName(packageName + "." + className).getMethod("type").invoke(null); + + return type; + } catch (IllegalAccessException + | IllegalArgumentException + | InvocationTargetException + | NoSuchMethodException + | SecurityException + | ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return null; + } + + /** + * Creates a new instance of the type of the specified object. + * @param object object + * @return new instance of the type of the specified object + */ + public static VObject newInstance(VObject object) { + return newInstance(getType(object)); + } + + /** + * Creates a new instance of the specified type. + * @param type type to instantiate + * @return new instance of the specified type + */ + public static VObject newInstance(Type type) { + return newInstance(type.getName()); + } + + /** + * Creates a new instance of the specified type. + * @param typeName type to instantiate + * @return new instance of the specified type + */ + public static VObject newInstance(String typeName) { + + try { + return (VObject) Class.forName(typeName).getMethod("newInstance").invoke(null); + } catch (IllegalAccessException + | IllegalArgumentException + | InvocationTargetException + | NoSuchMethodException + | SecurityException + | ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return null; + + } +} \ No newline at end of file diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/ChangesImpl.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/ChangesImpl.java index 560648f2..a654c2e5 100644 --- a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/ChangesImpl.java +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/ChangesImpl.java @@ -243,7 +243,6 @@ public void start() { @SuppressWarnings("unchecked") private void registerChangeListener(VObject vObj, PropertyChangeListener objListener) { - Iterator it = vObj.vmf().content().iterator(VIterator.IterationStrategy.UNIQUE_NODE); while (it.hasNext()) { diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/DiffingImpl.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/DiffingImpl.java new file mode 100644 index 00000000..9d06f721 --- /dev/null +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/DiffingImpl.java @@ -0,0 +1,450 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ +/** + * Don't rely on this API. Seriously, don't rely on it! + */ +package eu.mihosoft.vmf.runtime.core.internal; + +import eu.mihosoft.vmf.runtime.core.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public class DiffingImpl implements Diffing { + static private VObject sourceObject; + static private VObject targetObject; + private static VObject input_deepCopy; + + static private NodeData[] nodeTable_input; + static private NodeData[] nodeTable_target; + static private List map; + + static private NodeData[] newTable; + + static private List allChangesList; + static private boolean printChanges = false; + + public void init(VObject target){ + targetObject = target; + InitChanges.init(sourceObject, targetObject); + } + + /** + * Method to perform all changes + */ + static void change() { + input_deepCopy = sourceObject.vmf().content().deepCopy(); + + nodeTable_input = InitChanges.getIndexTable_original_inorder(); + nodeTable_target = InitChanges.getIndexTable_clone_inorder(); + map = InitChanges.getMapping(); + allChangesList = new ArrayList<>(); + + VIterator count_it = targetObject.vmf().content().iterator(VIterator.IterationStrategy.CONTAINMENT_TREE); + int cloneSize = (int) count_it.asStream().count(); + + /* + newTable will contain all new nodes that are needed to create the new Object. + */ + newTable = new NodeData[cloneSize]; + for (int[] i : map) { + if (i[1] != 0 && i[0] != 0) { + newTable[i[1]-1] = nodeTable_input[i[0]-1]; + newTable[i[1]-1].setInorderParent(nodeTable_target[i[1]-1].getInorderParent()); + } + } + + /* + Perform all deletions first. + */ + for (int[] i : map) { + if (i[1] == 0) { + deleteChange(i[0]); + } + } + + /* + Create all new nodes. They are saved in the newTable. + The relationships are not set yet. + */ + for (int[] i : map) { + if (i[0] == 0) { + createNodes2Add(i[1]); + } + } + + + + /* + Now perform all insertions and set relationships accordingly. Then perform all + renaming tasks. To capture all changes correctly the change-recorder has to be set + to the according current Object where relationships are being set. This happens directly + inside the setRelations() and renameChange() methods. + */ + setRelations(); + renameChange(); + + /* + We revert all changes. The changes will only be applied when + applyChange() is called. + */ + List revertList = new ArrayList<>(allChangesList); + + Collections.reverse(revertList); + revertList.forEach( + evt -> { + evt.undo(); //@TODO:: Check if undoable? + } + ); + + //@TODO:: Is necessary but might be corrupting changelist + sourceObject = (VObject) nodeTable_input[nodeTable_input.length-1].getObject(); + } + + public void setSource(VObject sObj){ + sourceObject = sObj; + } + + public void printChanges(){ + int num_changes = allChangesList.size(); + + System.out.println("---------------- Changes List: --------------------"); + System.out.println("#changes: " + num_changes+"\n"); + + allChangesList.forEach( + (evt)-> { + System.out.println("evt: " + evt.propertyName()); + if(evt.propertyChange().isPresent()) { + System.out.println(" -> oldValue: " + evt.propertyChange().get().oldValue()); + System.out.println(" -> newValue: " + evt.propertyChange().get().newValue()); + System.out.println(" "); + } else if (evt.listChange().isPresent()) { + System.out.println(" -> " + evt.listChange().get().toStringWithDetails()); + } + } + ); + } + + /** + * Print step by step solution + * @param doPrint print if true + * @return boolean, whether the changes were successful + */ + public boolean applyChanges(boolean doPrint) { + printChanges = doPrint; + return applyChanges(); + } + + public boolean applyChanges(){ + //Print method --> Show all changes on console + if(printChanges){ + System.out.println("---------------- Apply changes: ------------------"); + System.out.println(" "); + System.out.println("Before Changes: " + sourceObject); + System.out.println(" "); + allChangesList.forEach(c-> { + System.out.println("Change --> "); + System.out.println(sourceObject); + System.out.println(" "); + }); + } + + if(! sourceObject.toString().equals(input_deepCopy.toString())){ + throw new RuntimeException( "Problem occurred while undoing Changes." ); + } + + //Apply all changes + allChangesList.forEach(c-> { + c.apply(c.object()); + }); + + sourceObject = (VObject) newTable[newTable.length-1].getObject(); + + if(printChanges) { + System.out.println("--------------- Changes Correct? -----------------"); + System.out.println(" "); + System.out.println("Original: " + sourceObject); + System.out.println("Clone: " + targetObject); + System.out.println("Original equals clone?: " + sourceObject.toString().equals(targetObject.toString())); + } + sourceObject.vmf().changes().clear(); + + /* + If the diffing failed we can retry the procedure. + For example if objects are in the wrong order in a List, this will help. + */ + if(!sourceObject.toString().equals(targetObject.toString())){ + int numRetries = 10; + for(int i=0; i getChanges(){ + return allChangesList; + } + + /** + * Remove nodes from the input object + * @param indexDeleteNode index of the node that has to be deleted + */ + private static void deleteChange(int indexDeleteNode) { + AtomicReference nodeToDelete + = new AtomicReference<>((VObject) nodeTable_input[indexDeleteNode - 1].getObject()); + + if(indexDeleteNode == nodeTable_input.length){ + /* + This is the case if the root gets deleted. + We only allow this if the child of the root is distinct. + If we find multiple child nodes the tree would split when deleting the root, + we cannot allow this case. + */ + AtomicBoolean childSet = new AtomicBoolean(false); + VObject rootNode = (VObject) nodeTable_input[indexDeleteNode - 1].getObject(); + rootNode.vmf().reflect().properties().forEach( + property -> { + if (property.annotationByKey("vmf_contains").isPresent()) { + if (property.getType().isListType()) { + if(((List) property.get()).size() == 1 && childSet.get()) { + throw new RuntimeException( "Deletion of Root causes splitting of Tree." ); + } + if(((List) property.get()).size() > 1) { + throw new RuntimeException( "Deletion of Root causes splitting of Tree." ); + } + if(((List) property.get()).size() == 1 && !childSet.get()) { + nodeToDelete.set((VObject) ((List) property.get()).get(0)); + childSet.set(true); + } + } else{ + if(property.get() != null && !childSet.get()){ + nodeToDelete.set((VObject) property.get()); + childSet.set(true); + } + if(property.get() != null && childSet.get()){ + throw new RuntimeException( "Deletion of Root causes splitting of Tree." ); + } + } + } + } + ); + sourceObject = nodeToDelete.get(); + } + else { + /* + For any other case we simply unset the parent node. + We register a change as a deletion. + */ + nodeToDelete.get().vmf().reflect().properties().forEach( + property -> { + /* + In case of deletion of an intermediate Node we need to make + sure, that all children of "nodeToDelete" get deleted as well. + */ + + if (property.annotationByKey("vmf_contains").isPresent()) { + if (property.getType().isListType()) { + while(!((List) property.get()).isEmpty()){ + Object obj = ((List) property.get()).get(0); + nodeToDelete.get().vmf().changes().start(); + ((List) property.get()).remove(obj); + nodeToDelete.get().vmf().changes().stop(); + allChangesList.addAll(nodeToDelete.get().vmf().changes().all()); + } + } else { + nodeToDelete.get().vmf().changes().start(); + property.unset(); + nodeToDelete.get().vmf().changes().stop(); + } + } + + /* + Here we delete the parent of "nodeToDelete" + */ + + if (property.annotationByKey("vmf_container").isPresent()) { + if (property.getType().isListType()) { + throw new RuntimeException("Parent is of List Type."); + } else { + VObject parentObject = (VObject) property.get(); + parentObject.vmf().changes().start(); + property.unset(); + parentObject.vmf().changes().stop(); + allChangesList.addAll(parentObject.vmf().changes().all()); + } + } + } + ); + } + } + + /** + * Set the parent/child relations + */ + @SuppressWarnings("unchecked") + private static void setRelations(){ + for (int i = 0; i < newTable.length-1; i++) { + Object node = newTable[i].getObject(); + VObject root = (VObject) nodeTable_input[nodeTable_input.length-1].getObject(); + int parent = newTable[i].getInorderParent(); + int containmentIndex = nodeTable_target[i].getContainmentIndex(); + String containment = newTable[i].getContainment(); + + /* + If a node is in new intermediate Node we need to record some extra changes. + For example: Map {A{C}} -> {A{B{C}}} + Here node "B" will be inserted between "A" and "C". This happens in two steps. + First delete "C" from "A", then add it to "B". We therefor need a recorder on both + nodes "A" and "B". We simply start recording on the (old) root node. Since the intermediate + node has not yet been added to the root, there won't be any duplications + regarding the changes. + */ + boolean intermediateNode = false; + for (int[] j : map) { + if(j[1] == parent && j[0] == 0 && j[1]!=newTable.length){ + intermediateNode = true; + root.vmf().changes().start(); + } + } + /* + If a node is a former root-node it has no containment. Therefor we need to set it. + */ + if(containment.isEmpty()){ + newTable[i].setContainment(nodeTable_target[i].getContainment()); + containment = newTable[i].getContainment(); + } + + final String fin_containment = containment; + VObject parentNode = (VObject) newTable[parent - 1].getObject(); + parentNode.vmf().changes().start(); + parentNode.vmf().reflect().properties().forEach( + property -> { + if (property.annotationByKey("vmf_contains").isPresent() + && property.annotationByKey("vmf_contains").get().getValue().equals(fin_containment)) { + if (property.getType().isListType()) { + /* + Add if not already contained. + The Node is added at the correct index, but we need to check whether the index + is not out of bound. + */ + if (!((List) property.get()).contains(node)) { + int currentLength = ((List) property.get()).size(); + if(containmentIndex-1 > currentLength){ + ((List) property.get()).add(node); + } + else { + ((List) property.get()).add(containmentIndex, node); + } + } + } else { + //Change if property is not already set the the object + if (!Objects.equals(property.get(), node)) { + property.set(node); + } + } + } + } + ); + + if(intermediateNode){ + root.vmf().changes().stop(); + allChangesList.addAll(root.vmf().changes().all()); + } + + parentNode.vmf().changes().stop(); + allChangesList.addAll(parentNode.vmf().changes().all()); + } + } + + /** + * Creates new nodes if necessary + * @param ind Index from the mapping + */ + private static void createNodes2Add(int ind) { + /* Get all properties of the new Element we want to add.*/ + VObject cloneObject = (VObject) nodeTable_target[ind-1].getObject(); + String cloneContainment = nodeTable_target[ind-1].getContainment(); + int cloneInOrdInd = nodeTable_target[ind-1].getInorderParent(); + int containmentIndex = nodeTable_target[ind-1].getContainmentIndex(); + + /* + * Create a new node with given properties + * Set all properties except for containments (Parents/Children) + */ + Type cloneType = VMFUtil.getType(cloneObject); + VObject newNode = null; + if (cloneType != null) { + newNode = VMFUtil.newInstance(cloneType); + List newProp = newNode.vmf().reflect().properties(); + List cloneProp = cloneObject.vmf().reflect().properties(); + int numProp = cloneProp.size(); + for(int j=0; j prop_or = ((VObject) nodeTable_target[i[1]-1].getObject()) + .vmf().reflect().properties(); + List prop = object.vmf().reflect().properties(); + object.vmf().changes().start(); + for(int j=0; j. All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ +/** + * Don't rely on this API. Seriously, don't rely on it! + */ +package eu.mihosoft.vmf.runtime.core.internal; + +import eu.mihosoft.vmf.runtime.core.VIterator; +import eu.mihosoft.vmf.runtime.core.VMF; +import eu.mihosoft.vmf.runtime.core.VObject; + +import java.util.*; + +/** + * Class to generate nodeTables. A nodeTable is a List of NodeData-Objects and therefor saves + * each Node present in the inputTree separately. This structure helps to save the important + * containment information and simplifies access to specific Nodes in the tree. + * + * E.g. If given the index i of a node we can simply call the Object by accessing the according + * spot of the nodeTable: nodeTable[i].getObject() + */ +public class GenerateNodeTable { + + /** + * Constructs a nodeTable. + * @param inputTree VMF-Objects that gets mapped onto a nodeTable + * @return The nodeTable in the ordering picked up by the CONTAINMENT_TREE iterator. + */ + public static NodeData[] generate(VMF inputTree) { + + VIterator input_it = inputTree.content().iterator(VIterator.IterationStrategy.CONTAINMENT_TREE); + VIterator count_it = inputTree.content().iterator(VIterator.IterationStrategy.CONTAINMENT_TREE); + int n_iterations = (int) count_it.asStream().count(); + + NodeData[] nodeTable= new NodeData[n_iterations]; + + Object parent_object = input_it.next(); + + NodeData parent = new NodeData(); + parent.setObject(parent_object); + //Root has no parent: We initialize with -1 + parent.setParent(-1); + parent.setContainment(""); + nodeTable[0] = parent; + + int index = 1; + + while(input_it.hasNext()){ + VObject next_el = input_it.next(); + NodeData current_element = new NodeData(); + //Save new element in indexTable[i] + current_element.setObject(next_el); + + /* + Iterate the properties and look for the object with the "parent" annotation. + Save this element as the parent for the current element. + */ + final int current_index = index; + next_el.vmf().reflect().properties().forEach( + property -> { + if(property.annotationByKey("vmf_container").isPresent()){ + + // Find the parent Object and set the parent_index + for(int i=0; i< current_index; i++){ + if(Objects.equals(nodeTable[i].getObject(),property.get())){ + current_element.setParent(i); + } + } + // Iterate over all containers + ((VObject) property.get()).vmf().reflect().properties().forEach( + parent_property -> { + if(parent_property.annotationByKey("vmf_contains").isPresent()) { + // Check if containment is List Type and look for matching Object + if(parent_property.getType().isListType() && + ((List) parent_property.get()).contains(next_el)){ + for(int i=0; i<((List) parent_property.get()).size(); i++){ + if(((List) parent_property.get()).get(i).equals(next_el)){ + current_element.setContainmentIndex(i); + } + } + String parent_annotation_value = parent_property + .annotationByKey("vmf_contains").get().getValue(); + current_element.setContainment(parent_annotation_value); + } else if(Objects.equals(parent_property.get(),next_el)){ + String parent_annotation_value = parent_property + .annotationByKey("vmf_contains").get().getValue(); + current_element.setContainment(parent_annotation_value); + } + + } + } + ); + } + }); + /* + next_el.vmf().reflect().properties().forEach( + property -> { + if(property.annotationByKey("vmf_contains").isPresent()){ + if(property.getType().isListType()){ + int numChildren = ((List) property.get()).size(); + System.out.println(current_element.getObject()); + System.out.println("!!!!" + numChildren); + current_element.setNumChildren(numChildren); + } + } + } + ); + */ + index += 1; + + nodeTable[current_index] = current_element; + } + return nodeTable; + } + + /** + * Since APTED uses an inOrdering for its Algorithm the nodeTable needs to be + * transformed accordingly + * @param inputTable nodeTable in ordering as given by the iterator + * @return inOrdered nodeTable + */ + public static NodeData[] transform_inOrder(NodeData[] inputTable){ + ArrayDeque current_queue = new ArrayDeque<>(); + Stack buffer_stack = new Stack<>(); + int size = inputTable.length; + + NodeData[] inOrderTable = new NodeData[size]; + + + for(int i=0; i inputTable[i+1].getParent()){ + current_queue.add(inputTable[i]); + while( buffer_stack.peek().getParent() >= inputTable[i+1].getParent()){ + current_queue.add(buffer_stack.pop()); + } + } + else{ + buffer_stack.push(inputTable[i]); + } + } + else{ + buffer_stack.push(inputTable[i]); + while(!buffer_stack.empty()){ + current_queue.add(buffer_stack.pop()); + } + } + } + + for(int i=0; i. All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ +/** + * Don't rely on this API. Seriously, don't rely on it! + */ +package eu.mihosoft.vmf.runtime.core.internal; + +import eu.mihosoft.ext.apted.distance.APTED; +import eu.mihosoft.ext.apted.node.Node; +import eu.mihosoft.vmf.runtime.core.VObject; + +import java.util.List; + +/** + * The InitChanges() class sets up all required structures to compute the mapping. + */ +public class InitChanges { + /** + * @param nodeTable_input_inorder Contains the inordered nodeTable for the input object + * @param nodeTable_target_inorder Contains the inordered nodeTable for the target object + * @param mapping Contains the mapping between the two objects + * @param editDistance Number of edit steps needed + * @param printMapping Boolean whether to print out the mapping + */ + static private NodeData[] nodeTable_input_inorder; + static private NodeData[] nodeTable_target_inorder; + static private List mapping; + static private int editDistance; + + /** + * @param input The original objects that needs to be changed + * @param target The objects that contains the changes to be made + */ + static public void init(VObject input, VObject target) { + NodeData[] nodeTableInput = GenerateNodeTable.generate(input.vmf()); + NodeData[] nodeTableTarget = GenerateNodeTable.generate(target.vmf()); + /* + * Generating the nodeTable + */ + nodeTable_input_inorder + = GenerateNodeTable.transform_inOrder(nodeTableInput); + nodeTable_target_inorder + = GenerateNodeTable.transform_inOrder(nodeTableTarget); + + /* + * Constructing the NodeData + */ + Node t1 = Tree2NodeData.tree2NodeData(nodeTableInput); + Node t2 = Tree2NodeData.tree2NodeData(nodeTableTarget); + + /* + * Initializing apted (compute mapping and distance) + */ + APTED apted = new APTED<>(new NodeDataCostModel()); + editDistance = (int)apted.computeEditDistance(t1, t2); + apted.init(t1, t2); + mapping = apted.computeEditMapping(); + + DiffingImpl.change(); + } + + /** + * @return Returns the inordered nodeTable for the original Object + */ + static NodeData[] getIndexTable_original_inorder(){ + return nodeTable_input_inorder; + } + + /** + * @return Returns the inordered nodeTable for the clone Object + */ + static NodeData[] getIndexTable_clone_inorder(){ + return nodeTable_target_inorder; + } + + /** + * @return Returns the mapping + */ + static List getMapping(){ + return mapping; + } + + /** + * @return editDistance + */ + static int getEditDistance(){ + return editDistance; + } +} diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/NodeData.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/NodeData.java new file mode 100644 index 00000000..6a8e7dd8 --- /dev/null +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/NodeData.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ +/** + * Don't rely on this API. Seriously, don't rely on it! + */ +package eu.mihosoft.vmf.runtime.core.internal; + +/** + * Data structure to save Nodes and their properties + */ +public class NodeData { + /** + * @param object Holds the corresponding Object + * @param parent Saves the index of the parent Object + * @param inOrderParent Saves the index of the parent Object in inOrdering + * @param containment Saves the containment relationship between the Object and its parent + * @param containmentIndex Saves the index at which an Object is contained in its parent + */ + private Object object; + private int parent; + private int inOrderParent; + private String containment; + private int containmentIndex = 0; + + public Object getObject() { return object; } + + public void setObject(Object object) { + this.object = object; + } + + int getInorderParent() { + return inOrderParent; + } + + void setInorderParent(int inOrderParent) { + this.inOrderParent = inOrderParent; + } + + public int getParent() { + return parent; + } + + public void setParent(int parent) { + this.parent = parent; + } + + public String getContainment() { + return containment; + } + + public void setContainment(String containment) { + this.containment = containment; + } + + public int getContainmentIndex() { return containmentIndex; } + + public void setContainmentIndex(int containmentIndex) { this.containmentIndex = containmentIndex; } + +} diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/NodeDataCostModel.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/NodeDataCostModel.java new file mode 100644 index 00000000..01e9303d --- /dev/null +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/NodeDataCostModel.java @@ -0,0 +1,104 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ +/** + * Don't rely on this API. Seriously, don't rely on it! + */ +package eu.mihosoft.vmf.runtime.core.internal; + +import eu.mihosoft.ext.apted.costmodel.CostModel; +import eu.mihosoft.ext.apted.node.Node; +import eu.mihosoft.vmf.runtime.core.Property; +import eu.mihosoft.vmf.runtime.core.VObject; + +import java.util.Objects; + +/** + * Defines the cost for all changes and therefor directs the mapping + */ +public class NodeDataCostModel implements CostModel{ + /** + * @param n Input nodeData + * @return Deletion of a Node always costs "1" + */ + public float del(Node n) { + return 1.0f; + } + + /** + * @param n Input nodeData + * @return Insertion of a Node always costs "1" + */ + public float ins(Node n) { + return 1.0f; + } + + /** + * Renaming a node means looking for differing properties and exchanging them + * + * @param n1 Input nodeData of the original Object + * @param n2 Input nodeData of the clone Object + * @return The cost of renaming + * + * renFactor: The cost of a single renaming operation + * newCost: will contain the final renaming cost + */ + public float ren(Node n1, Node n2) { + float renFactor = 0.2f; + float newCost = 0f; + + /* + * If Objects are not of the same class the cost is maximal, since they can't be renamed + * We force del/ins operations instead. + */ + if(!Objects.equals(n2.getNodeData().getObject().getClass(), + n1.getNodeData().getObject().getClass())){ + return Float.MAX_VALUE; + } else{ + /* + * Objects are of same class + */ + Object n1_obj = n1.getNodeData().getObject(); + int n1_propSize = ((VObject) n1_obj).vmf().reflect().properties().size(); + /* + * We assume that if n1 and n2 are of same class they have the same # of properties + */ + for (int i = 0; i < n1_propSize; i++) { + Property n1_prop = ((VObject) n1.getNodeData().getObject()).vmf().reflect().properties().get(i); + Property n2_prop = ((VObject) n2.getNodeData().getObject()).vmf().reflect().properties().get(i); + /* + * We make the renaming a little more expensive for every property that differs + */ + if (!Objects.equals(n1_prop.get(), n2_prop.get()) + && !n1_prop.getType().isListType() + && !n2_prop.getType().isListType() + && !n1_prop.getType().isModelType() + && !n2_prop.getType().isModelType()) { + newCost += renFactor; + } + } + } + return newCost; + } + +} diff --git a/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/Tree2NodeData.java b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/Tree2NodeData.java new file mode 100644 index 00000000..a0a0e3e9 --- /dev/null +++ b/runtime/src/main/java/eu/mihosoft/vmf/runtime/core/internal/Tree2NodeData.java @@ -0,0 +1,59 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ +/** + * Don't rely on this API. Seriously, don't rely on it! + */ +package eu.mihosoft.vmf.runtime.core.internal; + +import eu.mihosoft.ext.apted.node.Node; + +/** + * Creates a Node Object to make the Tree compatible for the APTED-Algorithm + */ +public class Tree2NodeData { + + //Create a new Node Object out of the nodeTable + @SuppressWarnings("unchecked") + public static Node tree2NodeData(NodeData[] nodeTable){ + + //treeNode_List contains the TreeObjects in the order they are present in the indexTable + int size = nodeTable.length; + Node[] treeNode_List = new Node[size]; + + //Fill the treeNode_List + for(int i=0; i treeNode = new Node<>(nodeTable[i]); + treeNode_List[i] = treeNode; + + //Set the parent-child relation + int parent_index = nodeTable[i].getParent(); + if(parent_index>-1){ + treeNode_List[parent_index].getChildren().add(treeNode); + } + + } + + return treeNode_List[0]; + } +} diff --git a/test-suite/build.gradle b/test-suite/build.gradle index 3dbb56a5..01e5729e 100644 --- a/test-suite/build.gradle +++ b/test-suite/build.gradle @@ -12,7 +12,7 @@ buildscript { } dependencies { - classpath "eu.mihosoft.vmf:vmf-gradle-plugin:${commonProps.get("publication.version")}" + classpath "eu.mihosoft.vmf:vmf-gradle-plugin:0.2.7.6" } } @@ -29,7 +29,7 @@ apply plugin: 'eu.mihosoft.vmf' idea { module { dependencies { - compile group: 'eu.mihosoft.vmf', name: 'vmf', version: commonProps.get("publication.version") + compile group: 'eu.mihosoft.vmf', name: 'vmf', version: '0.2.7.6' } } } @@ -65,9 +65,8 @@ dependencies { testCompile 'org.hamcrest:hamcrest-library:1.3' - testCompile group: 'eu.mihosoft.vmf', name: 'vmf', version: commonProps.get("publication.version") - - compile group: 'eu.mihosoft.vmf', name: 'vmf-runtime', version: commonProps.get("publication.version") + testCompile group: 'eu.mihosoft.vmf', name: 'vmf', version: '0.2.7.6' + compile group: 'eu.mihosoft.vmf', name: 'vmf-runtime', version: '0.2.7.6' compile group: 'org.mdkt.compiler', name: 'InMemoryJavaCompiler', version: '1.3.0' compile group: 'org.codehaus.groovy', name: 'groovy-console', version: '2.0.1' diff --git a/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/CostModelTest.java b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/CostModelTest.java new file mode 100644 index 00000000..359f63aa --- /dev/null +++ b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/CostModelTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * Copyright 2017 Samuel Michaelis. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ + +package eu.mihosoft.vmftest.diffing; + +import eu.mihosoft.vmf.runtime.core.Diffing; +import eu.mihosoft.ext.apted.node.Node; +import eu.mihosoft.vmf.runtime.core.VObject; +import eu.mihosoft.vmf.runtime.core.internal.*; +import org.junit.Assert; +import org.junit.Test; + +public class CostModelTest { + public static VObject test0; + public static VObject test1; + public static VObject test4; + public static VObject test5; + + public static NodeDataCostModel costModel; + public static Node t0; + public static Node t1; + public static Node t4; + public static Node t5; + + public static void init(){ + diffing.NodeTestObject.main(); + test0 = diffing.NodeTestObject.testObject0; //{A{B}{C}} + test1 = diffing.NodeTestObject.testObject1; //{A{B{D}{E}}{C}} + test4 = diffing.NodeTestObject.testObject4; //{X{B}{C}} + test5 = diffing.NodeTestObject.testObject5; //{X{Y}{Z}} + + NodeData[] indexTable0 = GenerateNodeTable.generate(test0.vmf()); + NodeData[] indexTable1 = GenerateNodeTable.generate(test1.vmf()); + NodeData[] indexTable4 = GenerateNodeTable.generate(test4.vmf()); + NodeData[] indexTable5 = GenerateNodeTable.generate(test5.vmf()); + + t0 = Tree2NodeData.tree2NodeData(indexTable0); + t1 = Tree2NodeData.tree2NodeData(indexTable1); + t4 = Tree2NodeData.tree2NodeData(indexTable4); + t5 = Tree2NodeData.tree2NodeData(indexTable5); + costModel = new NodeDataCostModel(); + } + + /* + Testing Object: {A{B}{C}} and {A{B{D}{E}}{C}} + Simple cost-check for deletion/insertion. + */ + @Test + public void myCostModelTest0() { + init(); + Assert.assertEquals(costModel.del(t0),1.0, 0.01); + Assert.assertEquals(costModel.ins(t0),1.0, 0.01); + + Assert.assertEquals(costModel.del(t1),1.0, 0.01); + Assert.assertEquals(costModel.ins(t1),1.0, 0.01); + } + + /* + Simple renaming cost-check. Renaming one property costs 0.2, we only look + at the root node. + Testing: {A{B}{C}} and {X{B}{C}} -> Should cost 0.2 + Testing: {X{B}{C}} and {X{Y}{Z}} -> Should cost 0.0 + */ + @Test + public void myCostModelTest1() { + init(); + Assert.assertEquals(costModel.ren(t0,t4), 0.2, 0.01); + Assert.assertEquals(costModel.ren(t4,t5), 0.0, 0.01); + } +} diff --git a/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/IndexTableTest.java b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/IndexTableTest.java new file mode 100644 index 00000000..998da0a6 --- /dev/null +++ b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/IndexTableTest.java @@ -0,0 +1,193 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * Copyright 2017 Samuel Michaelis. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ + +package eu.mihosoft.vmftest.diffing; + +import eu.mihosoft.vmf.runtime.core.Diffing; +import eu.mihosoft.vmf.runtime.core.VObject; +import eu.mihosoft.vmf.runtime.core.internal.*; +import diffing.NodeTestObject; +import org.junit.Rule; +import org.junit.Test; +import org.junit.Assert; +import org.junit.rules.ExpectedException; + +public class IndexTableTest { + private static NodeData[] nodeTable0; + private static NodeData[] nodeTable1; + private static NodeData[] nodeTable2; + private static NodeData[] nodeTable3; + private static NodeData[] nodeTable0Traits; + private static VObject test0; + private static VObject test1; + + private static void init(){ + NodeTestObject.main(); + test0 = diffing.NodeTestObject.testObject0; //{A{B}{C}} + test1 = NodeTestObject.testObject1; //{A{B{D}{E}}{C}} + VObject test2 = NodeTestObject.testObject2; //{A{B{C}}{B{C}}} - Clones + VObject test3 = NodeTestObject.testObject3; //{A{B{C}}{B{C}}} - No clones + VObject test0Traits = NodeTestObject.testObject0WithTrait; //{A{B}{C}} w\Traits + + nodeTable0 = GenerateNodeTable.generate(test0.vmf()); + nodeTable1 = GenerateNodeTable.generate(test1.vmf()); + nodeTable2 = GenerateNodeTable.generate(test2.vmf()); + nodeTable3 = GenerateNodeTable.generate(test3.vmf()); + nodeTable0Traits = GenerateNodeTable.generate(test0Traits.vmf()); + } + + /* + Testing Object: {A{B}{C}} and {A{B{D}{E}}{C}} + Simple Object check. + */ + @Test + public void myIndexTest0() { + init(); + Assert.assertEquals(nodeTable0[0].getObject(), test0); + Assert.assertEquals(nodeTable1[0].getObject(), test1); + } + + /* + Testing Object: {A{B}{C}} + Simple containment check. + */ + @Test + public void myIndexTest1() { + init(); + Assert.assertEquals(nodeTable0[0].getContainment(), ""); + Assert.assertEquals(nodeTable0[1].getContainment(), "children"); + Assert.assertEquals(nodeTable0[2].getContainment(), "children"); + } + + /* + Testing Object: {A{B{D}{E}}{C}} + Simple test for parent-child relation in the containment tree. + */ + @Test + public void myIndexTest2() { + init(); + Assert.assertEquals(nodeTable1[0].getParent(), -1); //A + Assert.assertEquals(nodeTable1[1].getParent(), 0); //B + Assert.assertEquals(nodeTable1[2].getParent(), 1); //D + Assert.assertEquals(nodeTable1[3].getParent(), 1); //E + Assert.assertEquals(nodeTable1[4].getParent(), 0); //C + } + + /* + Testing Object: {A{B}{C}} with additional Traits + This test should show that the traits are set correctly. + */ + @Test + public void myIndexTest3() { + init(); + Trait trait0 = ((TreeNode) nodeTable0Traits[0].getObject()).getTraits().get(0); + Trait trait1 = ((TreeNode) nodeTable0Traits[0].getObject()).getTraits().get(1); + Assert.assertEquals(trait0.getName(), "TraitA0"); + Assert.assertEquals(trait1.getName(), "TraitA1"); + Assert.assertEquals(trait0.getTrait(), "Test0"); + Assert.assertEquals(trait1.getTrait(), "Test1"); + } + + /* + Testing Object: {A{B}{C}} with additional Traits + This test should show that different containments are identified correctly. + */ + @Test + public void myIndexTest4() { + init(); + Trait trait0 = ((TreeNode) nodeTable0Traits[0].getObject()).getTraits().get(0); + Trait trait1 = ((TreeNode) nodeTable0Traits[0].getObject()).getTraits().get(1); + + Assert.assertEquals(trait0.getAffiliation(), nodeTable0Traits[0].getObject()); + Assert.assertEquals(trait1.getAffiliation(), nodeTable0Traits[0].getObject()); + + Assert.assertEquals(nodeTable0Traits[0].getContainment(), ""); + Assert.assertEquals(nodeTable0Traits[1].getContainment(), "children"); + Assert.assertEquals(nodeTable0Traits[2].getContainment(), "trait"); + Assert.assertEquals(nodeTable0Traits[3].getContainment(), "children"); + Assert.assertEquals(nodeTable0Traits[4].getContainment(), "trait"); + Assert.assertEquals(nodeTable0Traits[5].getContainment(), "trait"); + Assert.assertEquals(nodeTable0Traits[6].getContainment(), "trait"); + } + + /* + Testing Object: {A{B{C}}{B{C}}} + The Elements B and C are not identical Objects. Test if treated as such. + */ + @Test + public void myIndexTest5() { + init(); + Assert.assertEquals(nodeTable2[0].getParent(), -1); + Assert.assertEquals(nodeTable2[1].getParent(), 0); + Assert.assertEquals(nodeTable2[2].getParent(), 1); + Assert.assertEquals(nodeTable2[3].getParent(), 0); + Assert.assertEquals(nodeTable2[4].getParent(), 3); + } + + /* + Testing Object: {A{B{C}}{B{C}}} + The Elements B and C are the same Objects. They should not appear in the containment tree + a second time. + */ + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void myIndexTest6() { + init(); + Assert.assertEquals(nodeTable3.length, 3); + Assert.assertEquals(nodeTable3[0].getParent(), -1); + Assert.assertEquals(nodeTable3[1].getParent(), 0); + Assert.assertEquals(nodeTable3[2].getParent(), 1); + + exception.expect(ArrayIndexOutOfBoundsException.class); + Assert.assertNull(nodeTable3[3]); + Assert.assertNull(nodeTable3[4]); + } + + /* + Testing Object: {A{B{D}{E}}{C}} + Test the reordering of the indexTable objects in InOrder. + Original Ordering: A,B,D,E,C + InOrder: D,E,B,C,A + */ + @Test + public void myInorderTest0() { + init(); + NodeData[] inOrder1 = GenerateNodeTable.transform_inOrder(nodeTable1); + + Assert.assertEquals(inOrder1[0].getParent(), 1); //D + Assert.assertEquals(inOrder1[1].getParent(), 1); //E + Assert.assertEquals(inOrder1[2].getParent(), 0); //B + Assert.assertEquals(inOrder1[3].getParent(), 0); //C + Assert.assertEquals(inOrder1[4].getParent(), -1); //A + + Assert.assertEquals(((TreeNode)inOrder1[0].getObject()).getName(), "D"); + Assert.assertEquals(((TreeNode)inOrder1[1].getObject()).getName(), "E"); + Assert.assertEquals(((TreeNode)inOrder1[2].getObject()).getName(), "B"); + Assert.assertEquals(((TreeNode)inOrder1[3].getObject()).getName(), "C"); + Assert.assertEquals(((TreeNode)inOrder1[4].getObject()).getName(), "A"); + } +} diff --git a/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/MappingTest.java b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/MappingTest.java new file mode 100644 index 00000000..f2df2529 --- /dev/null +++ b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/MappingTest.java @@ -0,0 +1,2335 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * Copyright 2017 Samuel Michaelis. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ + +package eu.mihosoft.vmftest.diffing; + +import eu.mihosoft.vmf.runtime.core.internal.*; +import diffing.NodeTestObject; +import eu.mihosoft.vmf.runtime.core.VObject; +import org.junit.Assert; +import org.junit.Test; + +public class MappingTest { + /* + Testing if Objects equal after making changes. + Tested on all combinations of test Objects provided by the NodeTestObjects class. + */ + + // MAP 0 --> + // _______________________________ + @Test + public void testMapping0To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 1 --> + // _______________________________ + + @Test + public void testMapping1To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 2 --> + // _______________________________ + + @Test + public void testMapping2To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 3 --> + // _______________________________ + + @Test + public void testMapping3To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 4 --> + // _______________________________ + + @Test + public void testMapping4To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping4To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject4; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 5 --> + // _______________________________ + + @Test + public void testMapping5To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping5To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject5; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 6 --> + // _______________________________ + + @Test + public void testMapping6To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping6To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject6; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 7 --> + // _______________________________ + + @Test + public void testMapping7To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping7To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject7; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 8 --> + // _______________________________ + + @Test + public void testMapping8To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping8To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject8; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 9 --> + // _______________________________ + + @Test + public void testMapping9To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping9To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject9; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 10 --> + // _______________________________ + + @Test + public void testMapping10To0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping10To3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject10; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 0Traits --> + // _______________________________ + + @Test + public void testMapping0TraitsTo0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping0TraitsTo3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject0WithTrait; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 1Traits --> + // _______________________________ + + @Test + public void testMapping1TraitsTo0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping1TraitsTo3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject1WithTrait; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 2Traits --> + // _______________________________ + + @Test + public void testMapping2TraitsTo0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping2TraitsTo3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject2WithTrait; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + // MAP 3Traits --> + // _______________________________ + + @Test + public void testMapping3TraitsTo0(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject0; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo1(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject1; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo2(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject2; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo3(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject3; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo4(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject4; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo5(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject5; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo6(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject6; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo7(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject7; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo8(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject8; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo9(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject9; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo10(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject10; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo0Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject0WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo1Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject1WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo2Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject2WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + + @Test + public void testMapping3TraitsTo3Traits(){ + NodeTestObject.main(); + VObject original = NodeTestObject.testObject3WithTrait; + VObject clone = NodeTestObject.testObject3WithTrait; + InitChanges.init(original, clone); + MakeChanges.printChanges(); + Assert.assertTrue(MakeChanges.applyChange()); + } + +} + diff --git a/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/NodeTestObject.java b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/NodeTestObject.java new file mode 100644 index 00000000..faeb3a2e --- /dev/null +++ b/test-suite/src/test/java/eu/mihosoft/vmftest/diffing/NodeTestObject.java @@ -0,0 +1,238 @@ +/* + * Copyright 2017-2019 Michael Hoffer . All rights reserved. + * Copyright 2017-2019 Goethe Center for Scientific Computing, University Frankfurt. All rights reserved. + * Copyright 2017 Samuel Michaelis. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * If you use this software for scientific research then please cite the following publication(s): + * + * M. Hoffer, C. Poliwoda, & G. Wittum. (2013). Visual reflection library: + * a framework for declarative GUI programming on the Java platform. + * Computing and Visualization in Science, 2013, 16(4), + * 181–192. http://doi.org/10.1007/s00791-014-0230-y + */ + +package eu.mihosoft.vmftest.diffing; + +import eu.mihosoft.vmf.runtime.core.VObject; +import eu.mihosoft.vmftest.diffing.vmfmodel.TreeNode; +import eu.mihosoft.vmftest.diffing.vmfmodel.Trait; +import eu.mihosoft.vmftest.annotations.AnnotatedModel; + +public class NodeTestObject { + public static VObject testObject0; + public static VObject testObject1; + public static VObject testObject2; + public static VObject testObject3; + public static VObject testObject4; + public static VObject testObject5; + public static VObject testObject6; + public static VObject testObject7; + public static VObject testObject8; + public static VObject testObject9; + public static VObject testObject10; + public static VObject testObject0WithTrait; + public static VObject testObject1WithTrait; + public static VObject testObject2WithTrait; + public static VObject testObject3WithTrait; + + public static void main() { + //testObject0: {A{B}{C}} + TreeNode nodeA0 = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB0 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC0 = TreeNode.newBuilder().withName("C").build(); + nodeA0.getChildren().add(nodeB0); + nodeA0.getChildren().add(nodeC0); + testObject0 = nodeA0; + + //testObject1: {A{B{D}{E}}{C}} + TreeNode nodeA1 = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB1 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC1 = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeD1 = TreeNode.newBuilder().withName("D").build(); + TreeNode nodeE1 = TreeNode.newBuilder().withName("E").build(); + nodeA1.getChildren().add(nodeB1); + nodeA1.getChildren().add(nodeC1); + nodeB1.getChildren().add(nodeD1); + nodeB1.getChildren().add(nodeE1); + testObject1 = nodeA1; + + //testObject2: {A{B{C}}{B{C}}} - Clones + TreeNode nodeA2 = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB2 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC2 = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeB2_clone = TreeNode.newBuilder().withName("E").build(); + TreeNode nodeC2_clone = TreeNode.newBuilder().withName("F").build(); + nodeA2.getChildren().add(nodeB2); + nodeA2.getChildren().add(nodeB2_clone); + nodeB2.getChildren().add(nodeC2); + nodeB2_clone.getChildren().add(nodeC2_clone); + testObject2 = nodeA2; + + //testObject3: {B{D}} + TreeNode nodeB3 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeD3 = TreeNode.newBuilder().withName("D").build(); + nodeB3.getChildren().add(nodeD3); + testObject3 = nodeB3; + + //testObject4: {X{B}{C}} + TreeNode nodeX4 = TreeNode.newBuilder().withName("X").build(); + TreeNode nodeB4 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC4 = TreeNode.newBuilder().withName("C").build(); + nodeX4.getChildren().add(nodeB4); + nodeX4.getChildren().add(nodeC4); + testObject4 = nodeX4; + + //testObject5: {X{Y}{Z}} + TreeNode nodeX5 = TreeNode.newBuilder().withName("X").build(); + TreeNode nodeY5 = TreeNode.newBuilder().withName("Y").build(); + TreeNode nodeZ5 = TreeNode.newBuilder().withName("Z").build(); + nodeX5.getChildren().add(nodeY5); + nodeX5.getChildren().add(nodeZ5); + testObject5 = nodeX5; + + //testObject6: {B{C{D}}} + TreeNode nodeB6 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC6 = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeD6 = TreeNode.newBuilder().withName("D").build(); + nodeB6.getChildren().add(nodeC6); + nodeC6.getChildren().add(nodeD6); + testObject6 = nodeB6; + + //testObject7: {X{B{C{D}}} + TreeNode nodeX7 = TreeNode.newBuilder().withName("X").build(); + TreeNode nodeB7 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC7 = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeD7 = TreeNode.newBuilder().withName("D").build(); + nodeX7.getChildren().add(nodeB7); + nodeB7.getChildren().add(nodeC7); + nodeC7.getChildren().add(nodeD7); + testObject7 = nodeX7; + + //testObject8: {X{B{C{D}{E}}} + TreeNode nodeX8 = TreeNode.newBuilder().withName("X").build(); + TreeNode nodeB8 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC8 = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeD8 = TreeNode.newBuilder().withName("D").build(); + TreeNode nodeE8 = TreeNode.newBuilder().withName("E").build(); + nodeX8.getChildren().add(nodeB8); + nodeB8.getChildren().add(nodeC8); + nodeC8.getChildren().add(nodeD8); + nodeC8.getChildren().add(nodeE8); + testObject8 = nodeX8; + + //testObject9: {A{B{X}}{D{E}}} + TreeNode nodeA9 = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB9 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeX9 = TreeNode.newBuilder().withName("X").build(); + TreeNode nodeD9 = TreeNode.newBuilder().withName("D").build(); + TreeNode nodeE9 = TreeNode.newBuilder().withName("E").build(); + nodeA9.getChildren().add(nodeB9); + nodeA9.getChildren().add(nodeD9); + nodeB9.getChildren().add(nodeX9); + nodeD9.getChildren().add(nodeE9); + testObject9 = nodeA9; + + //testObject10: {A{B}{X{C}}} + TreeNode nodeA10 = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB10 = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC10 = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeX10 = TreeNode.newBuilder().withName("X").build(); + nodeA10.getChildren().add(nodeB10); + nodeA10.getChildren().add(nodeX10); + nodeX10.getChildren().add(nodeC10); + testObject10 = nodeA10; + + + //testObject0WithTrait: {A{B}{C}} + //Traits for A: Name="TraitA0", Trait="Test0" + //Traits for A: Name="TraitA1", Trait="Test1" + //Traits for B: Name="TraitB0", Trait="Test0" + //Traits for C: Name="TraitC0", Trait="Test0" + TreeNode nodeA0WithTraits = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB0WithTraits = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC0WithTraits = TreeNode.newBuilder().withName("C").build(); + nodeA0WithTraits.getChildren().add(nodeB0WithTraits); + nodeA0WithTraits.getChildren().add(nodeC0WithTraits); + Trait traitA0_object0 = Trait.newBuilder().withName("TraitA0").withTrait("Test0").build(); + Trait traitA1_object0 = Trait.newBuilder().withName("TraitA1").withTrait("Test1").build(); + Trait traitB0_object0 = Trait.newBuilder().withName("TraitB0").withTrait("Test0").build(); + Trait traitC0_object0 = Trait.newBuilder().withName("TraitC0").withTrait("Test0").build(); + nodeA0WithTraits.getTraits().add(traitA0_object0); + nodeA0WithTraits.getTraits().add(traitA1_object0); + nodeB0WithTraits.getTraits().add(traitB0_object0); + nodeC0WithTraits.getTraits().add(traitC0_object0); + testObject0WithTrait = nodeA0WithTraits; + + //testObject1WithTrait: {A{B{D}{E}}{C}} + //Traits for A: Name="TraitA0", Trait="Test0" + //Traits for A: Name="TraitA1", Trait="Test1" + //Traits for B: Name="TraitB0", Trait="Test0" + //Traits for E: Name="TraitE0", Trait="Test0" + TreeNode nodeA1WithTraits = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB1WithTraits = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC1WithTraits = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeD1WithTraits = TreeNode.newBuilder().withName("D").build(); + TreeNode nodeE1WithTraits = TreeNode.newBuilder().withName("E").build(); + nodeA1WithTraits.getChildren().add(nodeB1WithTraits); + nodeA1WithTraits.getChildren().add(nodeC1WithTraits); + nodeB1WithTraits.getChildren().add(nodeD1WithTraits); + nodeB1WithTraits.getChildren().add(nodeE1WithTraits); + Trait traitA0_object1 = Trait.newBuilder().withName("TraitA0").withTrait("Test0").build(); + Trait traitA1_object1 = Trait.newBuilder().withName("TraitA1").withTrait("Test1").build(); + Trait traitB0_object1 = Trait.newBuilder().withName("TraitB0").withTrait("Test0").build(); + Trait traitE0_object1 = Trait.newBuilder().withName("TraitE0").withTrait("Test0").build(); + nodeA0WithTraits.getTraits().add(traitA0_object1); + nodeA0WithTraits.getTraits().add(traitA1_object1); + nodeB0WithTraits.getTraits().add(traitB0_object1); + nodeC0WithTraits.getTraits().add(traitE0_object1); + testObject1WithTrait = nodeA1WithTraits; + + //testObject2WithTraits: {A{B{C}}{B{C}}} + //Traits for B left: Name="TraitBLeft", Trait="Left" + //Traits for B right: Name="TraitBRight", Trait="Right" + TreeNode nodeA2WithTraits = TreeNode.newBuilder().withName("A").build(); + TreeNode nodeB2WithTraits = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC2WithTraits = TreeNode.newBuilder().withName("C").build(); + TreeNode nodeB2_cloneWithTraits = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeC2_cloneWithTraits = TreeNode.newBuilder().withName("C").build(); + nodeA2WithTraits.getChildren().add(nodeB2WithTraits); + nodeA2WithTraits.getChildren().add(nodeB2_cloneWithTraits); + nodeB2WithTraits.getChildren().add(nodeC2WithTraits); + nodeB2_cloneWithTraits.getChildren().add(nodeC2_cloneWithTraits); + Trait traitBLeft_object3 = Trait.newBuilder().withName("TraitBLeft").withTrait("Left").build(); + Trait traitBRight_object3 = Trait.newBuilder().withName("TraitRight").withTrait("Right").build(); + nodeB2WithTraits.getTraits().add(traitBLeft_object3); + nodeB2_cloneWithTraits.getTraits().add(traitBRight_object3); + testObject2WithTrait = nodeA2WithTraits; + + //testObject3WithTrait: {B{D}} + //Traits for B: Name="TraitB0", Trait="Test0" + //Traits for D: Name="TraitD0", Trait="Test0" + //Traits for D: Name="TraitD1", Trait="Test1" + //Traits for D: Name="TraitD2", Trait="Test2" + TreeNode nodeB3WithTraits = TreeNode.newBuilder().withName("B").build(); + TreeNode nodeD3WithTraits = TreeNode.newBuilder().withName("D").build(); + nodeB3WithTraits.getChildren().add(nodeD3WithTraits); + Trait traitB0_object3 = Trait.newBuilder().withName("TraitB0").withTrait("Test0").build(); + Trait traitD0_object3 = Trait.newBuilder().withName("TraitD0").withTrait("Test0").build(); + Trait traitD1_object3 = Trait.newBuilder().withName("TraitD1").withTrait("Test1").build(); + Trait traitD2_object3 = Trait.newBuilder().withName("TraitD2").withTrait("Test2").build(); + nodeB3WithTraits.getTraits().add(traitB0_object3); + nodeD3WithTraits.getTraits().add(traitD0_object3); + nodeD3WithTraits.getTraits().add(traitD1_object3); + nodeD3WithTraits.getTraits().add(traitD2_object3); + testObject3WithTrait = nodeB3WithTraits; + } +} diff --git a/test-suite/src/test/vmf/eu/mihosoft/vmftest/diffing/vmfmodel/Trait.java b/test-suite/src/test/vmf/eu/mihosoft/vmftest/diffing/vmfmodel/Trait.java new file mode 100644 index 00000000..ca5283d8 --- /dev/null +++ b/test-suite/src/test/vmf/eu/mihosoft/vmftest/diffing/vmfmodel/Trait.java @@ -0,0 +1,13 @@ +package eu.mihosoft.vmftest.diffing.vmfmodel; + +import eu.mihosoft.vmf.core.Annotation; +import eu.mihosoft.vmf.core.Container; + +public interface Trait { + String getName(); + String getTrait(); + + @Container(opposite="traits") + @Annotation(key="vmf_container", value="affiliation") + TreeNode getAffiliation(); +} diff --git a/test-suite/src/test/vmf/eu/mihosoft/vmftest/diffing/vmfmodel/TreeNode.java b/test-suite/src/test/vmf/eu/mihosoft/vmftest/diffing/vmfmodel/TreeNode.java new file mode 100644 index 00000000..1d7cd438 --- /dev/null +++ b/test-suite/src/test/vmf/eu/mihosoft/vmftest/diffing/vmfmodel/TreeNode.java @@ -0,0 +1,23 @@ +package eu.mihosoft.vmftest.diffing.vmfmodel; + +import eu.mihosoft.vmf.core.Annotation; +import eu.mihosoft.vmf.core.Container; +import eu.mihosoft.vmf.core.Contains; + +public interface TreeNode { + String getName(); + + @Container(opposite = "children") + @Annotation(key = "vmf_container", value = "parent") + TreeNode getParent(); + + @Contains(opposite = "parent") + @Annotation(key = "vmf_contains", value = "children") + TreeNode[] getChildren(); + + //Additional traits can be attached to an Object + + @Contains(opposite="affiliation") + @Annotation(key="vmf_contains", value="trait") + Trait[] getTraits(); +}