modeltype ECORE uses 'http://www.eclipse.org/emf/2002/Ecore';

transformation mapInherits(in inModel : ECORE, out outModel : ECORE);
 
main() {
	var container : EAnnotation := null;
	var root : EPackage := null; 
	object root: {
		name := 'root';
		eClassifiers += root.map createSource(object EClass{})
			.map toEClassNamedOnly();		
		eClassifiers += root.map createSource(object EClass{})
			.map toEClassModelNamed();
		eClassifiers += root.map createSource(object EClass{})
			.map multipleInherited1();
		eClassifiers += root.map createSource(object EClass{})
			.map multipleInherited2();	
	};
	
	-- check precondition and param passing
	var fooSrc := root.map createSource(object EClass{});
	var fooResult := fooSrc.map foo(null); -- precondition fails
	assert fatal (fooResult.oclIsTypeOf(EClass));
	assert fatal (fooSrc.resolveIn(EClass::baseMap, EClass)->isEmpty());
	assert fatal (fooSrc.resolveIn(EClass::foo, EClass)->notEmpty());	
	
	var fooResult2 := fooSrc.map foo(root); -- precondition holds
	assert fatal (fooResult = fooResult2); 
	assert fatal (fooResult.oclIsTypeOf(EClass));
	-- check updated root by baseMap
	root.eAnnotations->one(source = 'EClass::baseMap');
	
	assert fatal (fooSrc.resolveIn(EClass::baseMap, EClass)->notEmpty());
	assert fatal (fooSrc.resolveIn(EClass::foo, EClass)->notEmpty());
}


mapping EClass::baseMap(inout p1Another : ENamedElement) : EClass
	when { p1Another <> null } {
	name := 'baseMap_' + p1Another.name;
	end {
		p1Another.eAnnotations += object EAnnotation {
			source := 'EClass::baseMap';
		};
	}
} 

mapping inout EClass::foo(inout p1 : EPackage) : EClass 
	inherits EClass::baseMap  
{
	init { result := self; }
}

abstract mapping inout EModelElement::setupModelElement() : EModelElement {
	eAnnotations += object EAnnotation {
		source := 'EModelElement::setupModelElement';
	}
}

abstract mapping inout ENamedElement::setupNamedElementOnly() : ENamedElement {
	init {
		var suffix := '_ENamedElement::setupNamedElementOnly';
		self.eAnnotations += object EAnnotation { source := 'ENamedElement::setupNamedElementOnly' };
	}
	name := if(self.name <> null) then self.name + suffix else suffix endif;
	eAnnotations += object EAnnotation { 
		source := 'ENamedElement::setupNamedElementOnly';
	}	
}

abstract mapping ENamedElement::setupNamedModelElement() : ENamedElement 
	inherits EModelElement::setupModelElement
{
	eAnnotations += object EAnnotation { 
		source := 'ENamedElement::setupNamedModelElement';
	}
}


abstract mapping EClassifier::toNamedEModelEClassifier() : EClassifier 
	inherits ENamedElement::setupNamedModelElement 
{
	eAnnotations += object EAnnotation { 
		source := 'EClassifier::toNamedEModelEClassifier';
	}
}


abstract mapping inout EClassifier::toNamedOnlyEClassifier() : EClassifier
	inherits ENamedElement::setupNamedElementOnly {
	init {
		self.eAnnotations += object EAnnotation { source := 'EClassifier::toNamedOnlyEClassifier' };		
	}
	eAnnotations += object EAnnotation { 
		source := 'EClassifier::toNamedOnlyEClassifier';
	}	
}

mapping inout EClass::toEClassNamedOnly() : EClass 
	inherits EClassifier::toNamedOnlyEClassifier {
	init {
		result := object EClass {
			name := 'toEClassNamedOnly'; -- should be reset in setupNamedElements
		};
		
		self.eAnnotations += object EAnnotation { source := 'EClass::toEClassNamedOnly' };
	}
	eAnnotations += object EAnnotation { 
		source := 'EClass::toEClassNamedOnly';
	}		
}  

mapping EClass::toEClassModelNamed() : EClass 
	inherits EClassifier::toNamedEModelEClassifier {
	name := 'toEClassModelNamed';
	eAnnotations += object EAnnotation { 
		source := 'EClass::toEClassModelNamed';
	}		
} 

-- should have only the first mapping name set
mapping EClass::multipleInherited1() : EClass 
	inherits EClassifier::toNamedEModelEClassifier, EClassifier::toNamedOnlyEClassifier {
	name := 'multipleInherited1';
	eAnnotations += object EAnnotation { 
		source := 'EClass::multipleInherited1';
	}		
} 

mapping EClass::multipleInherited2() : EClass 
	inherits EClassifier::toNamedOnlyEClassifier, 
		EClassifier::toNamedEModelEClassifier,
		ENamedElement::setupNamedElementOnly -- should not be called, involved in the above mapping 
{
	name := 'multipleInherited2';
	eAnnotations += object EAnnotation { 
		source := 'EClass::multipleInherited2';
	}		
} 


mapping inout EPackage::createSource(inout source : EClass) : EClass {
	init {
		source.name := 'source';
		result := source;	
		var srcContainer := self.map createSourceContainer();
		assert fatal (srcContainer <> self);
	}
	population {
		object srcContainer: {
			eClassifiers += result;
		}	
	}
}

mapping inout EPackage::createSourceContainer() : EPackage {
	population {
		object result: {	
			name := 'src';			
		};
		object self: {
			eSubpackages += result;
		}
	}
}