Manoj Keshavaprakash
Manoj Keshavaprakash

Reputation: 17

How to programmatically create a child instance of model instance in EMF

I am working on developing a test suite for EMF models. I have a metamodel (.ecore file (class diagram)) created using the graphical editor.

Now I am able to create the dynamic instances programmatically, but in my metamodel I have a composition (Containment reference) wherein I want to create child instance of the contained class (programmatically).

Please find the below information for reference

Class diagram:

metamodel

JUnit testcase:

public class DynamicTest extends TestCase
{
    public void testCreateModel() throws IOException {
    ResourceSet rs = new ResourceSetImpl();
    rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", 
    new XMIResourceFactoryImpl());
    Resource res = rs.createResource( URI.createFileURI( 
    "C:/Users/Manoj/Documents/FreshStart/Company/model/company.ecore" ));
    res.load(null);
    EPackage metapackage = (EPackage)res.getContents().get(0);
    System.out.println("meta Package "+metapackage.getName());
    EFactory employeeFactoryInstance = metapackage.getEFactoryInstance();
    EClass employeeClass = (EClass)metapackage.getEClassifier("Employee");
    EObject employeeObject = employeeFactoryInstance.create(employeeClass);
    EAttribute employeeName = employeeClass.getEAllAttributes().get(0);
    EAttribute employeeManager = employeeClass.getEAllAttributes().get(1);
    employeeObject.eSet(employeeName, "Manoj");
    employeeObject.eSet(employeeManager, "Albert");
    String empName = (String)employeeObject.eGet(employeeName);
    String empManager = (String)employeeObject.eGet(employeeManager);
    ResourceSet resourseSet = new ResourceSetImpl();
    resourseSet.getPackageRegistry().put(metapackage.getNsURI(), 
    metapackage); 

    ResourseSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put
    ("*", new XMIResourceFactoryImpl());
    Resource resource = 
    ResourseSet.createResource(URI.createURI("./model/Employee.xmi"));
    resource.getContents().add(employeeObject);
    Map options = new HashMap();
    options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
    try 
    {
        resource.save(options);
    } catch (IOException e) {
        // TODO: handle exception
        e.printStackTrace();
    }
    EPackage metapackage1 = (EPackage)res.getContents().get(0);
    EFactory departmentFactoryInstance = metapackage1.getEFactoryInstance();
    EClass departmentClass = 
    (EClass)metapackage1.getEClassifier("Department");
    EObject departmentObject = 
    departmentFactoryInstance.create(departmentClass);
    EAttribute departmentName = departmentClass.getEAllAttributes().get(0);
    EAttribute departmentNumber = 
    departmentClass.getEAllAttributes().get(1);
    EObject depRef = employeeClass.eContainmentFeature().eContents().get(0);
    departmentObject.eSet(departmentName, "SMS");
    departmentObject.eSet(departmentNumber, 101);
    String depName = (String)departmentObject.eGet(departmentName);
    Integer depNumber = (Integer)departmentObject.eGet(departmentNumber);
    ResourceSet resSet = new ResourceSetImpl();
    resSet.getPackageRegistry().put(metapackage1.getNsURI(), metapackage1);
    resSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", 
    new XMIResourceFactoryImpl());
    Resource res1 = 
    resSet.createResource(URI.createURI("./model/Department.xmi"));  
    res1.getContents().add(departmentObject);
    Map options1 = new HashMap();
    options1.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
    try 
    {
        res1.save(options1);
    } catch (IOException e) {
        // TODO: handle exception
        e.printStackTrace();
    }         
  }
}

Kindly help to me to create new child instance from department instance programmatically.

Upvotes: 0

Views: 1017

Answers (1)

Lii
Lii

Reputation: 12122

You add an object to a multi-valued feature by first getting the list that is the feature value. Then you add an element to that list.

Example:

EStructuralFeature employeeFeature = departmentClass.getEStructuralFeature("employee");
@SuppressWarnings("unchecked")  // Safe cast as long as only Employees are added
List<EObject> employees = (List<EObject>) departmentObject.eGet(employeeFeature);
employees.add(employeeObject);

A few notes about your code:

  • employeeObject should not be added to a resource if it is contained in departmentObject. Only the top-level objects, which are not contained by any other objects, should be added to a resource.
  • It is better to use EClass.getEStructuralFeature to get the right feature. In that way your code does not break if the order of the features is changed.
  • It's even better to get the EStructuralFeature from the reflection model objects, like this:

    EStructuralFeature employeeFeature = PackageClass.Literals.EMPLOYEE_FEATURE;
    

Upvotes: 3

Related Questions