blob: d30d2f7c67248f2d3da408a3e843fce9dd8eb138 [file] [log] [blame]
--@atlcompiler atl2006
--/*******************************************************************************
-- * Copyright (c) 2009 Ecole des Mines de Nantes.
-- * All rights reserved. This program and the accompanying materials
-- * are made available under the terms of the Eclipse Public License v1.0
-- * which accompanies this distribution, and is available at
-- * http://www.eclipse.org/legal/epl-v10.html
-- *
-- * Contributors:
-- * Kelly Garces - initial implementation and/or initial documentation
-- *******************************************************************************/
library EqualMM; -- Library Template
-- conceptual bindings
helper context EqualMM!AddedStructuralFeature def: getParent : EqualMM!WLink =
self.model.equalClasses
->union(self.model.addedClasses)
->flatten()
->select(e | e.rightElement.structuralFeatures.includes(self.rightElement))
->first();
helper context EqualMM!DeletedStructuralFeature def: getParent : EqualMM!WLink =
self.model.equalClasses
->union(self.model.deletedClasses)
->flatten()
->select(e | e.leftElement.structuralFeatures.includes(self.leftElement))
->first();
helper context EqualMM!EqualStructuralFeature def: getParent : EqualMM!EqualClass =
self.model.equalClasses
->select(e | e.leftElement.structuralFeatures.includes(self.leftElement) and
e.rightElement.structuralFeatures.includes(self.rightElement))
->first();
-- complex changes involving an associated class
helper context EqualMM!MovePropertyToOwned def : getParent : EqualMM!EqualClass =
self.getParentExtract;
helper context EqualMM!MovePropertyToOwner def : getParent : EqualMM!EqualClass =
self.getParentInline;
helper context EqualMM!ExtractClass def : getParent : EqualMM!EqualClass =
self.getParentExtract;
helper context EqualMM!InlineClass def : getParent : EqualMM!EqualClass =
self.getParentInline;
helper context EqualMM!EqualStructuralFeature def : getParentExtract : EqualMM!EqualClass =
self.model.equalClasses
->select (e |
e.leftElement = self.leftElement.owner
and
e.rightElement.references
->collect(e | e.type) --->debug('eTypes')
->select(e | e = self.rightElement.owner)
->notEmpty()
)
->first()
;
helper context EqualMM!EqualStructuralFeature def : getParentInline : EqualMM!EqualClass =
self.model.equalClasses
->select (e |
e.rightElement = self.rightElement.owner
and
e.leftElement.references
->collect(e | e.type)
->select(e | e = self.leftElement.owner)
->notEmpty()
)
->first();
-- complex changes involving a superclass
helper context EqualMM!PushProperty def : getParent : EqualMM!EqualClass =
self.model.equalClasses
->select(e |
e.leftElement.allSupertypes->collect(e | e.structuralFeatures)->flatten() --.debug('structuralFeaturesLeft') --leftProperty is contained by the superclasses of leftClass
->includes(self.leftElement)
and
(e.rightElement.structuralFeatures.includes(self.rightElement)--rightProperty is contained by rightClass or by the superclasses of rightClass
or
e.rightElement.allSupertypes->collect(e | e.structuralFeatures)->flatten()
->includes(self.rightElement)))
->first()
;
helper context EqualMM!PullProperty def : getParent : EqualMM!EqualClass =
self.model.equalClasses
->select(e |
(e.leftElement.structuralFeatures.includes(self.leftElement)
or
e.leftElement.allSupertypes->collect(e | e.structuralFeatures)->flatten()
->includes(self.leftElement))
and
e.rightElement.allSupertypes->collect(e | e.structuralFeatures)->flatten() --rightProperty is contained by the superclasses of rightClass
->includes(self.rightElement))
->first()
;
helper context EqualMM!ExtractSuperClass def : getParent : EqualMM!EqualClass =
self.model.equalClasses
->select(e |
e.leftElement.structuralFeatures.includes(self.leftElement)
and
e.rightElement.allSupertypes->collect(e | e.structuralFeatures)->flatten()
->includes(self.rightElement))
->first();
helper context EqualMM!FlattenProperty def : getParent : EqualMM!EqualClass =
self.model.equalClasses
->select(e |
e.leftElement.allSupertypes->collect(e | e.structuralFeatures)->flatten()
->includes(self.leftElement)
and
e.rightElement.structuralFeatures.includes(self.rightElement))
->first();
helper context EqualMM!AddedEnumLiteral def : getParent : OclAny =
self.model.equalEnumerations
->union(self.model.addedEnumerations)
->flatten()
->select(e | e.rightElement.literals.includes(self.rightElement))
->first();
helper context EqualMM!DeletedEnumLiteral def : getParent : OclAny =
self.model.equalEnumerations
->union(self.model.deletedEnumerations)
->flatten()
->select(e | e.leftElement.literals.includes(self.leftElement))
->first();
helper context EqualMM!MatchModel def : getCorrespondingEqualClass (class : OclAny) : EqualMM!EqualClass =
self.equalClasses->select (e | e.rightE.__xmiID__ = class.__xmiID__
or
e.leftE.__xmiID__ = class.__xmiID__ );
--@begin Helpers required by MappingIntersection and EqualMM2INRIAAlignement
helper context String def: refModelNameOutExt(projectName : String) : String =
self.refModelName(projectName).removeExt;
helper context EqualMM!ModelRef def: refModelName(projectName : String) : String =
self.ref.refModelName(projectName);
helper context EqualMM!ModelRef def: refModelNameOutExt(projectName : String) : String =
self.ref.refModelNameOutExt(projectName);
helper def : mmExt : String = '.ecore';
helper context String def: refModelName(projectName : String) : String =
--self.split(projectName)->last(); TODO why we get an array instead of a Sequence as indicated on the ATL reference, it seems this is a bug of the new vm;
self.substring((5 + projectName.size() + 8), self.size());
--../projectName/models/mapMName
--/../InstanceBasedMatching/models/classDiagram.ecore
helper context String def : removeExt : String =
self.substring(1, self.indexOf(thisModule.mmExt));
--@end Helpers required by MappingIntersection and EqualMM2INRIAAlignement
helper def : uniqueEqualModel : EqualMM!MatchModel = if EqualMM!MatchModel.allInstances()->isEmpty() then
OclUndefined
else
EqualMM!MatchModel.allInstances()->first()
endif;
helper def : equalModel(mName : String) : EqualMM!MatchModel =
EqualMM!MatchModel.allInstancesFrom(mName)->first();
helper context EqualMM!MatchModel def: mapEqualByModel : Map(String, EqualMM!Equal) =
self.ownedElement->iterate(e; rpm : Map(String, EqualMM!Equal) = Map{} |
rpm.including(e.xmiIDs_Equal, e)
);
-- returns a map having a leftElement "L" as key, and a set of equalElements with left equal to "L"
helper context EqualMM!MatchModel def: mapEqualByLeft : Map(String, Sequence(EqualMM!Equal)) =
self.ownedElement
->reject(e | e.oclIsKindOf(EqualMM!Added))
->iterate(e; rpm : Map(String, Sequence(EqualMM!Equal)) = Map{} |
if rpm.get(e.left.getReferredElement()).oclIsUndefined() then
rpm.including(e.left.getReferredElement(), Sequence{e})
else
rpm.including(e.left.getReferredElement(), rpm.get(e.left.getReferredElement()).append(e))
endif
);
helper context EqualMM!MatchModel def: mapEqualByRight : Map(String, Sequence(EqualMM!Equal)) =
self.ownedElement
->reject(e | e.oclIsKindOf(EqualMM!Deleted))
->iterate(e; rpm : Map(String, Sequence(EqualMM!Equal)) = Map{} |
if rpm.get(e.right.getReferredElement()).oclIsUndefined() then
rpm.including(e.right.getReferredElement(), Sequence{e})
else
rpm.including(e.right.getReferredElement(), rpm.get(e.right.getReferredElement()).append(e))
endif
);
-- BothMaxSim library
helper context EqualMM!MatchModel def: equalMaxSimByLeft : Map(String, Sequence(EqualMM!Equal)) =
self.mapEqualByLeft.getKeys()->iterate(e; rpm : Map(String, Sequence(EqualMM!Equal)) = Map{} |
rpm.including(e, thisModule.equalMaxSim(self.mapEqualByLeft.get(e))));
helper context EqualMM!MatchModel def: equalMaxSimByRight : Map(String, Sequence(EqualMM!Equal)) =
self.mapEqualByRight.getKeys()->iterate(e; rpm : Map(String, Sequence(EqualMM!Equal)) = Map{} |
rpm.including(e, thisModule.equalMaxSim(self.mapEqualByRight.get(e))));
-- ThresholdMaxDelta library
helper context EqualMM!MatchModel def: mapRangeByLeft : Map(String, TupleType(maxD : Real, max : Real)) =
self.mapEqualByLeft.getKeys()->iterate(e; rpm : Map(String, TupleType(maxD : Real, max : Real)) = Map{} |
rpm.including(e,
Tuple{
maxD = thisModule.maxSim(self.mapEqualByLeft.get(e)) - 0.08,
max = thisModule.maxSim(self.mapEqualByLeft.get(e))
}));
-- FilterRepetitiveLinks Library
-- this map was needed for matching ontologies because extracted metamodels are not well-formed
helper context EqualMM!MatchModel def: mapEqualByName : Map(String, EqualMM!Equal) =
self.ownedElement->iterate(e; map : Map(String, EqualMM!Equal) = Map{} |
map.including(e.name, e)
);
helper context EqualMM!WLink def: rightE : OclAny =
self.right.target;
helper context EqualMM!WLink def: leftE : OclAny =
self.left.target;
--TODO These helpers are used by External Transformations because they need to know the names of left and right metamodels
helper context EqualMM!WLink def: rightE(mName : String) : OclAny =
self.rightE;
helper context EqualMM!WLink def: leftE(mName : String) : OclAny =
self.leftE;
helper def: equalMaxSim(seq : Sequence(EqualMM!Equal)) : Sequence(EqualMM!Equal) =
if seq.isEmpty() then
OclUndefined
else
seq->select(e | e.similarity =
seq->reject(e | e.similarity.oclIsUndefined())->sortedBy(e | e.similarity).last().similarity)
endif;
helper def: maxSim(seq : Sequence(EqualMM!Equal)) : Real =
if thisModule.equalMaxSim(seq).oclIsUndefined() then
0
else
thisModule.equalMaxSim(seq)->first().similarity
endif;
-- Normalization
-- used in method that takes only one mapping model as input
helper context EqualMM!MatchModel def:equalModelMaxSim : Real =
thisModule.maxSim(self.ownedElement
->select(e | e.oclIsTypeOf(EqualMM!Equal))
);
helper def: totalSim(seq : Sequence(EqualMM!Equal)) : Real =
if seq.isEmpty() then
0
else
seq->collect(e | e.similarity)->sum()
endif;
helper context EqualMM!Equal def: equal (equal2 : EqualMM!Equal) : Boolean =
self.left.element.ref = equal2.left.element.ref
and
self.right.element.ref = equal2.right.element.ref;
helper def: leftEqual (equal1 : EqualMM!Equal, equal2 : EqualMM!Equal) : Boolean =
equal1.left.element.ref = equal2.left.element.ref;
helper def: rightEqual (equal1 : EqualMM!Equal, equal2 : EqualMM!Equal) : Boolean =
equal1.right.element.ref = equal2.right.element.ref;
helper def: leftRightEqual (equal1 : EqualMM!Equal, equal2 : EqualMM!Equal) : Boolean =
equal2.left.element.ref = equal1.right.element.ref;
helper def: rightLeftEqual (equal1 : EqualMM!Equal, equal2 : EqualMM!Equal) : Boolean =
equal2.right.element.ref = equal1.left.element.ref;
--InstancesLibrary
-- returns items of sequence which are instances of self
helper context EqualMM!Equal def: instancesEqual(sequence : Sequence(OclAny)) : Sequence(OclAny) =
sequence->select(e | self.isTypeOf(e));--, leftM, rightM, leftMM, rightMM
-- instance should be conform to Wlink or one of its extensions
helper context EqualMM!Equal def: isTypeOf (instance : OclAny) : Boolean =
self.leftE.name = self.typeName(instance.left.getReferredElement().oclType())
and
self.rightE.name = self.typeName(instance.right.getReferredElement().oclType());
helper context EqualMM!Equal def : typeName(type : OclAny) : String =
type.toString().substring(type.toString().indexOf('!')+2, type.toString().size());
helper context EqualMM!Added def:xmiIDs_Equal : String =
'_' + self.right.element.ref;
helper context EqualMM!Deleted def:xmiIDs_Equal : String =
self.left.element.ref + '_';
helper context EqualMM!Association def: xmiIDs_Equal : String =
'_';
helper context EqualMM!WLink def:xmiIDs_Equal : String =
if self.left.oclIsUndefined() and self.right.oclIsUndefined() then
'_'
else
if self.left.oclIsUndefined() then
'_' + self.right.element.ref
else if self.right.oclIsUndefined() then
self.left.element.ref + '_'
else if self.left.element.ref.oclIsUndefined() then
'_' + self.right.element.ref
else if self.right.element.ref.oclIsUndefined() then
self.left.element.ref + '_'
else
self.left.element.ref + '_' + self.right.element.ref
endif
endif
endif
endif
endif;
helper context EqualMM!MatchModel def: isEqualTo (left : OclAny, right : OclAny) : Boolean =
not self.mapEqualByModel.get(left.__xmiID__ + '_' + right.__xmiID__).oclIsUndefined();
helper def: mapEqual : Map(String, Sequence(EqualMM!Equal)) =
EqualMM!Equal.allInstances()->iterate(e; rpm : Map(String, Sequence(EqualMM!Equal)) = Map{} |
if rpm.get(e.xmiIDs_Equal).oclIsUndefined() then
rpm.including(e.xmiIDs_Equal, Sequence{e})
else
rpm.including(e.xmiIDs_Equal, rpm.get(e.xmiIDs_Equal).append(e))
endif
);
helper def: map : Map(String, EqualMM!Equal) =
EqualMM!Equal.allInstances()->iterate(e; rpm : Map(String, EqualMM!Equal) = Map{} |
rpm.including(e.xmiIDs_Equal, e));
helper context EqualMM!ElementRef def : getModelRef (model : String) : EqualMM!ModelRef =
if self.modelRef.ref = thisModule.equalModel(model).leftM.ref then
thisModule.equalModel(model).leftM
else
if self.modelRef.ref = thisModule.equalModel(model).rightM.ref then
thisModule.equalModel(model).rightM
else
OclUndefined
endif
endif;
-- Similarity Flooding
helper context EqualMM!MatchModel def: propMap : Map(String, Sequence(EqualMM!PropagationEdge)) =
self.ownedElement->iterate(e; map : OclAny = Map{} |
map.including(e.xmiIDs_Equal,
EqualMM!PropagationEdge.allInstances()
->select(f | f.incomingLink = e.xmiIDs_Equal)));
-- others helpers
-- This table was taken from the book Ontology Matching (pag. 96)
-- We assumed the column none represents the interval [1,1]
helper def: multTable : Map (String, Real) =
Map{
-- row 1
(
Tuple {
left = Tuple {lower = '0', upper = '-1'},
right = Tuple {lower = '0', upper = '-1'}
},
1.0
),
(
Tuple {
left = Tuple {lower = '0', upper = '-1'},
right = Tuple {lower = '1', upper = '-1'}
},
0.9
),
(
Tuple {
left = Tuple {lower = '0', upper = '-1'},
right = Tuple {lower = '0', upper = '1'}
},
0.7
),
(
Tuple {
left = Tuple {lower = '0', upper = '-1'},
right = Tuple {lower = '1', upper = '1'}
},
0.7
),
-- row 2
(
Tuple {
left = Tuple {lower = '1', upper = '-1'},
right = Tuple {lower = '0', upper = '-1'}
},
0.9
),
(
Tuple {
left = Tuple {lower = '1', upper = '-1'},
right = Tuple {lower = '1', upper = '-1'}
},
1.0
),
(
Tuple {
left = Tuple {lower = '1', upper = '-1'},
right = Tuple {lower = '0', upper = '1'}
},
0.7
),
(
Tuple {
left = Tuple {lower = '1', upper = '-1'},
right = Tuple {lower = '1', upper = '1'}
},
0.7
),
-- row 3
(
Tuple {
left = Tuple {lower = '0', upper = '1'},
right = Tuple {lower = '0', upper = '-1'}
},
0.7
),
(
Tuple {
left = Tuple {lower = '0', upper = '1'},
right = Tuple {lower = '1', upper = '-1'}
},
0.7
),
(
Tuple {
left = Tuple {lower = '0', upper = '1'},
right = Tuple {lower = '0', upper = '1'}
},
1.0
),
(
Tuple {
left = Tuple {lower = '0', upper = '1'},
right = Tuple {lower = '1', upper = '1'}
},
0.8
),
-- row 4
(
Tuple {
left = Tuple {lower = '1', upper = '1'},
right = Tuple {lower = '0', upper = '-1'}
},
0.7
),
(
Tuple {
left = Tuple {lower = '1', upper = '1'},
right = Tuple {lower = '1', upper = '-1'}
},
0.7
),
(
Tuple {
left = Tuple {lower = '1', upper = '1'},
right = Tuple {lower = '0', upper = '1'}
},
0.8
),
(
Tuple {
left = Tuple {lower = '1', upper = '1'},
right = Tuple {lower = '1', upper = '1'}
},
1.0
)
};
helper context EqualMM!MatchModel def: equalClasses : Sequence(EqualMM!EqualClass) =
self.ownedElement->select(e | e.oclIsKindOf(EqualMM!EqualClass));
helper context EqualMM!MatchModel def: equalEnumerations : Sequence(EqualMM!EqualClass) =
self.ownedElement->select(e | e.oclIsKindOf(EqualMM!EqualEnumeration));
helper context EqualMM!MatchModel def: addedClasses : Sequence(EqualMM!AddedClass) =
self.ownedElement->select(e | e.oclIsTypeOf(EqualMM!AddedClass));
helper context EqualMM!MatchModel def: deletedClasses : Sequence(EqualMM!DeletedClass) =
self.ownedElement->select(e | e.oclIsTypeOf(EqualMM!DeletedClass));
helper context EqualMM!MatchModel def: addedEnumerations : Sequence(EqualMM!AddedEnumeration) =
self.ownedElement->select(e | e.oclIsTypeOf(EqualMM!AddedEnumeration));
helper context EqualMM!MatchModel def: deletedEnumerations : Sequence(EqualMM!DeletedEnumeration) =
self.ownedElement->select(e | e.oclIsTypeOf(EqualMM!DeletedEnumeration));
helper context EqualMM!WLinkEnd def: target : OclAny =
self.getReferredElement();
helper context EqualMM!EqualAttribute def : primitiveTypesConvertionOperation : OclAny =
if self.left.target.type.name = 'EString' then
if self.right.target.type.name = 'EInteger' then
'toInteger'
else
if self.right.target.type.name = 'EDouble' then
'toReal'
else
OclUndefined
endif
endif
else
OclUndefined
endif;
helper context EqualMM!EqualStructuralFeature def : typeRestricted : Boolean =
if self.leftE.isAttribute and not self.leftE.type.isEnumeration then
if self.leftE.type.name = self.rightE.type.name then
false
else
true
endif
else
--self.leftE.oclIsTypeOf(EqualMM!EqualReference)
if self.model.isEqualTo(self.leftE.type, self.rightE.type) then
false
else
if self.leftE.isReference then
if self.leftE.type.supertypes
->select(e | self.model.isEqualTo(e, self.rightE.type))
->notEmpty() then
false
else
true
endif
else
true
endif
endif
endif;
helper context EqualMM!Equal def: linkingEnumeration : Boolean =
self.leftE.isEnumeration
and
self.rightE.isEnumeration;
helper context EqualMM!Equal def: linkingEnumLiteral : Boolean =
self.leftE.isEnumLiteral
and
self.rightE.isEnumLiteral;
helper context EqualMM!Equal def: linkingDataType : Boolean =
self.leftE.isDataType
and
self.rightE.isDataType;
helper context EqualMM!Equal def: linkingClass : Boolean =
self.leftE.isClass
and
self.rightE.isClass;
helper context EqualMM!Equal def: linkingReference : Boolean =
self.leftE.isReference
and
self.rightE.isReference;
helper context EqualMM!Equal def: linkingAttribute : Boolean =
self.leftE.isAttribute
and
self.rightE.isAttribute;
helper context EqualMM!Equal def: linkingStrFeature : Boolean =
self.leftE.isStructuralFeature
and
self.rightE.isStructuralFeature;
-- added
helper context EqualMM!Added def: linkingEnumeration : Boolean =
self.rightE.isEnumeration;
helper context EqualMM!Added def: linkingEnumLiteral : Boolean =
self.rightE.isEnumLiteral;
helper context EqualMM!Added def: linkingClass : Boolean =
self.rightE.isClass;
helper context EqualMM!Added def: linkingReference : Boolean =
self.rightE.isReference;
helper context EqualMM!Added def: linkingAttribute : Boolean =
self.rightE.isAttribute;
helper context EqualMM!Added def: linkingDataType : Boolean =
self.rightE.isDataType;
helper context EqualMM!Added def: linkingStrFeature : Boolean =
self.rightE.isStructuralFeature;
-- deleted
helper context EqualMM!Deleted def: linkingEnumeration : Boolean =
self.leftE.isEnumeration;
helper context EqualMM!Deleted def: linkingEnumLiteral : Boolean =
self.leftE.isEnumLiteral;
helper context EqualMM!Deleted def: linkingClass : Boolean =
self.leftE.isClass;
helper context EqualMM!Deleted def: linkingReference : Boolean =
self.leftE.isReference;
helper context EqualMM!Deleted def: linkingAttribute : Boolean =
self.leftE.isAttribute;
helper context EqualMM!Deleted def: linkingStrFeature : Boolean =
self.leftE.isStructuralFeature;
helper context EqualMM!Deleted def: linkingDataType : Boolean =
self.leftE.isDataType;
-- helpers required creation methods
helper context String def: leftName_rightName(right : String) : String =
if self.oclIsUndefined() and right.oclIsUndefined() then
'_'
else
if self.oclIsUndefined() then
'_' + right
else
if right.oclIsUndefined() then
self + '_'
else
self + '_' + right
endif
endif
endif;