package de.voelter.emf.dynamic;

import java.io.IOException;

import junit.framework.TestCase;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

import de.voelter.emf.dynamic.util.IOHelper;

/** 
 * This is a simple test that creates a dynamic EMF model and
 * then saves it to an EMF XMI file. And yes, it's not really a 
 * useful test - could have written it as a "main class", but 
 * I though test is nicer.
 @author MarkusVoelter
 */
public class MetaModelCreationTest extends TestCase {
  
  /** 
   * here we create the model and subsequently save it.
   */
  public void testCreateMetaModel() {
    // an EMF model is technically always an instance of
    // eCore, the EMF meta meta model. Each "meta layer" is
    // represented by a factory that can create instances of
    // the respective model elements as well as a package that
    // contains the elements themselves.
    EcoreFactory ef = EcoreFactory.eINSTANCE;
    EcorePackage ep = EcorePackage.eINSTANCE;
    
    // we now create our first (meta)class. These things
    // are EClasses. We use the factory of the respective
    // meta model to create the instance and then set the
    // name of the newly created class.
    EClass entityClass = ef.createEClass();
    entityClass.setName("Entity");

    // now we add an attribute called name to the
    // new metaclass Entity. 
    EAttribute nameAttr = ef.createEAttribute();
    nameAttr.setName("name");
    // here we use the respective eCore package to get
    // access to a data type defined in the eCore layer,
    // the EString, and use this as the type of the
    // attributes.
    nameAttr.setETypeep.getEString() );
    // finally, we add the attribute to the list of structural
    // features of the class. Structural features is the union
    // of attributes and references (see below).
    entityClass.getEStructuralFeatures().addnameAttr );
    
    // we now create another one, the attribute class.
    // you'll probably know where this is going. Entities have
    // attributes ... the usual data modelling stuff
    EClass attrClass = ef.createEClass();
    attrClass.setName("Attribute");
    // we also add a name attribute
    EAttribute attrNameAttr = ef.createEAttribute();
    attrNameAttr.setName("name");
    attrNameAttr.setETypeep.getEString() );
    attrClass.getEStructuralFeatures().addattrNameAttr );
    
    // and now we establish the actual relationship between
    // the two (meta) classes Entity and Attribute by defining
    // a reference. 
    EReference entity2Attribute = ef.createEReference();
    // the reference is unidirectional and it's owned by the
    // the entity class, so we add it to it's structural features.
    entityClass.getEStructuralFeatures().addentity2Attribute );
    // the target type is ... the attribute class!
    entity2Attribute.setETypeattrClass );
    // and yes, its a one-to-many
    entity2Attribute.setLowerBound(1);
    entity2Attribute.setUpperBound(-1);
    // it's containment...
    entity2Attribute.setContainment(true);
    // and the relationship has got a name
    entity2Attribute.setName"attributes" );

    // finally, we create a package to which we add the two classes.
    EPackage dataPackage = ef.createEPackage();
    
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    dataPackage.setNsPrefix("data");
    dataPackage.setNsURI("http://www.voelter.de/datametamodel");

    dataPackage.setName("dataPackage");
    dataPackage.getEClassifiers().add(entityClass);
    dataPackage.getEClassifiers().add(attrClass);

    // and then we store the file. Make sure the file 
    // name makes sense...
    try {
      IOHelper.storeAsXMIdataPackage, "l:/exampleWorkspace-v4-emf/emfdynamic/metamodel.ecore" );
    catch (IOException e) {
      faile.getMessage() );
    }

  }


  
}