IBM есть тема о динамической ЭМП.
Но это довольно прямолинейно, если вы знакомы с тем, как работает создание эдс. Каждый EPackage имеет свои собственные EFactory
и EPackage
экземпляры, которые обрабатывают создание (фабрику) или хранят информацию о самой метамодели (epackage).
Ecore имеет свой собственный EPackage
и EFactory
так что вполне возможно создать новые мета-модели на лету, как это:
/*Use the Ecore factory*/
EcoreFactory ecoreFactory = EcoreFactory.eINSTANCE;
/*Create your EPackage*/
EPackage myPackage = ecoreFactory.createEPackage();
/*set EPackage properties*/
myPackage.setName("myTest");
myPackage.setNsPrefix("myTest");
myPackage.setNsURI("http://com.myTest");
/*Create your first EClass*/
EClass myFirstEClass = ecoreFactory.createEClass();
myFirstEClass.setName("myClass");
/*Add to your EPackage's EClassifiers*/
/*EClasses and EDatatypes implement both EClassifiers*/
myPackage.getEClassifiers().add(myFirstEClass);
/*Create your first EAtttribute*/
EAttribute myFirstEAtt = ecoreFactory.createEAttribute();
myFirstEAtt.setName("name");
/*Use the EcorePackage Datatypes -> here EString*/
myFirstEAtt.setEType(EcorePackage.eINSTANCE.getEString());
/*use EStructuralFeatures to add your EAtt*/
/*EReferences and EAttributes are both EStructuralfeatures*/
myFirstEClass.getEStructuralFeatures().add(myFirstEAtt);
Update:
/*Create your second EClass*/
EClass mySecondEClass = ecoreFactory.createEClass();
mySecondEClass.setName("mySecondClass");
myPackage.getEClassifiers().add(mySecondEClass);
/*now, the firstClass should hold instances of secondClass*/
/*1. create EReference (Ereferences unlike EAttributes define relationships between EClasses)*/
EReference secondClassesRef = ecoreFactory.createEReference();
secondClassesRef.setName("secondClasses");
/*set containment true -> every EObject must have a Container*/
secondClassesRef.setContainment(true);
/*set Type to your EClass*/
secondClassesRef.setEType(mySecondEClass);
/*set upperbound -> now the reference is an EList*/
secondClassesRef.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY);
/*finally add ERef to EClass*/
myFirstEClass.getEStructuralFeatures().add(secondClassesRef);
/*and for example supertypes*/
myFirstEClass.getESuperTypes().add(mySecondEClass);
Теперь у вас есть свой собственный EPackage
с новый EClass
, который имеет EAttribute
имя типа EString
Теперь это возможно, чтобы сохранить новый EPackage к .ecore
файл, например так:
/*
* Save your EPackage to file ecore file:
*/
/*Initialize your EPackage*/
myPackage.eClass();
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
Map<String, Object> m = reg.getExtensionToFactoryMap();
/*add default .ecore extension for ecore file*/
m.put(EcorePackage.eNAME, new XMIResourceFactoryImpl());
// Obtain a new resource set
ResourceSet resSet = new ResourceSetImpl();
// create a resource
Resource resource = null;
try {
resource = resSet.createResource(URI.createFileURI("/Your/Path/To/Directory/myTest.ecore"));
} catch (Exception e) {
e.printStackTrace();
}
/*add your EPackage as root, everything is hierarchical included in this first node*/
resource.getContents().add(myPackage);
// now save the content.
try {
resource.save(Collections.EMPTY_MAP);
} catch (IOException e) {
e.printStackTrace();
}
и наоборот, если вы хотите, чтобы загрузить существующий Ecore EPackage:
/*
* load existing EPackage
*/
EcorePackage.eINSTANCE.eClass();
/*Initialize your EPackage*/
final Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
final Map<String, Object> m = reg.getExtensionToFactoryMap();
m.put(EcorePackage.eNAME, new XMIResourceFactoryImpl());
final ResourceSet resSet = new ResourceSetImpl();
Resource resource = null;
try {
resource = resSet.getResource(URI.createFileURI("/Your/Path/To/Directory/myTest.ecore"), true);
} catch (Exception e) {
e.printStackTrace();
}
/*load root and cast to EPackage*/
final EPackage root = (EPackage) resource.getContents().get(0);
Update: Ecore имеет от конечно, свою собственную метамодель. В Docs вы найдете отличный обзор архитектуры ecore.
Итак, если вы хотите использовать динамическую ЭМП, вам нужно это понять. Как я показал вам, очень просто создать EPackage
динамически, но вам нужно знать, как установить базовые атрибуты модели ecore (EClass, EAttributes, EReferences, EType, сдерживание, супертипы ...). Как только вы поняли архитектуру, это довольно легко. Посмотрите на UML-диаграмму внизу страницы.
Я также обновил код выше, чтобы показать вам, как инициализировать отношения между EClasses
Спасибо за вашу помощь, но у меня есть еще один вопрос: Как бы вы создать связь между двумя классами? Как нормальное отношение Reference или SuperType? – ConveniencePatterns
Обновлен мой ответ –