0

I'm working on xtext project and I'm generating objects through .xtext file. I want to add new attribute to one of the generated object. I saw in http://christiandietrich.wordpress.com/2011/07/22/customizing-xtext-metamodel-inference-using-xtend2/ the following code is generating a temp variable in ObjectValue but i want temp to be of type MyObject.

How to do so? where can i read about it?

import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage
import org.eclipse.emf.common.util.BasicEMap$Entry
import org.eclipse.emf.ecore.EClass
import org.eclipse.emf.ecore.EPackage
import org.eclipse.emf.ecore.EcoreFactory
import org.eclipse.emf.ecore.EcorePackage
import org.eclipse.xtext.GeneratedMetamodel
import org.eclipse.xtext.xtext.ecoreInference.IXtext2EcorePostProcessor

class CodeGeneratorClass implements IXtext2EcorePostProcessor {

    override process(GeneratedMetamodel metamodel) {
        metamodel.EPackage.process
    }

    def process(EPackage p) {
        for (c : p.EClassifiers.filter(typeof(EClass))) {
            if (c.name == "ObjectValue") {
                c.handle
            }
        }
    }

    def handle (EClass c) {
    val attr = EcoreFactory::eINSTANCE.createEAttribute
    attr.name = "temp"
    attr.EType = EcorePackage::eINSTANCE.EString
    c.EStructuralFeatures += attr
}
}
Dana Klein
  • 159
  • 1
  • 12

1 Answers1

1

First: MyObject must be described either by an EClass or an EDataType. A plain Java Object won't do it.

If MyObject is an EDataType then you must add an EAttribute in the handle method. Your handle method is almost right, only the EType must be adjusted:

attr.EType = MyPackage::eINSTANCE.MyObject

Otherwise: If MyObject is an EClass then you must add an EReference instead of an EAttribute. The handle method for this case looks like this:

def handleReference(EClass c){
    val ref = EcoreFactory::eINSTANCE.createEReference
    ref.name = "temp"
    ref.EType = MyPackage::eINSTANCE.MyObject
    c.EStructuralFeatures += ref
}

EDIT

In order to define a new, minimal EDataType and hook it up into the model the following snippet should work:

def void process(GeneratedMetamodel it){
     // create new dynamic EDataType
     val dataType = EcoreFactory::eINSTANCE.createEDataType => [
        name = 'MyObject'
        instanceTypeName = 'java.package.with.MyObject' 
    ]

    // register new EDataType in own model package
    EPackage.EClassifiers += dataType

    // attach as EAttribute to appropriate EClasses
    EPackage.EClassifiers.filter(typeof(EClass)).filter[name == 'ObjectValue'].forEach[
        EStructuralFeatures += EcoreFactory::eINSTANCE.createEAttribute => [
            name = "temp"
            EType = dataType
        ]
    ]
}
A.H.
  • 63,967
  • 15
  • 92
  • 126
  • @DanaKlein: Hmm. There are several ways to define an `EDataType`. And whether or not an `EDataType` is really the right thing is another question. For easy and simple things you can use the predefined stuff from `EcorePackage` - every `getXyz` method returning `EDataType`. If you really want to define your own EDataType then you should first consult a book about EMF. – A.H. Nov 01 '12 at 11:28
  • Thanks! Is it possible to return an Iterator object? s.t. the generated code would look like: public Iterator getIterator(){} – Dana Klein Nov 04 '12 at 14:01
  • Technically: I'm quite sure but I can't tell you offhand. But "Iterator" sound like you are trying to compute something. Then neither an attribute nor a reference would be the right thing to put into the model. In that case an operation sounds more appropriate. – A.H. Nov 04 '12 at 14:13
  • I'm trying to iterate over a object elements. so for that i want to generate a method with the signature: public Iterator getIterator(){...} – Dana Klein Nov 04 '12 at 14:44