diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/PatternActivator.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/PatternActivator.java
new file mode 100644
index 0000000..e7e50d1
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/PatternActivator.java
@@ -0,0 +1,104 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern;

+

+import org.osgi.framework.BundleContext;

+

+import org.eclipse.core.runtime.IProgressMonitor;

+

+import org.eclipse.egf.common.activator.AbstractActivator;

+import org.eclipse.egf.common.progress.IProgressRunnable;

+import org.eclipse.egf.common.progress.ProgressReporter;

+import org.eclipse.egf.fc.builder.java.JavaBuilderActivator;

+import org.eclipse.egf.fc.generator.java.JavaGeneratorActivator;

+import org.eclipse.egf.pattern.production.Messages;

+import org.eclipse.egf.pattern.production.PatternProducer;

+

+

+/**

+ * @author brocard

+ */

+public class PatternActivator extends AbstractActivator {

+  /**

+   * Activator shared instance.

+   */

+  private static PatternActivator __activator;

+  /**

+   * Pattern producer.

+   */

+  private PatternProducer _patternProducer;

+

+  /**

+   * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)

+   */

+  @Override

+  public void start(BundleContext context_p) throws Exception {

+    super.start(context_p);

+    // Get activator instance.

+    __activator = this;

+    // Ensure dependencies.

+    JavaGeneratorActivator.getDefault();

+    JavaBuilderActivator.getDefault();

+  }

+

+  /**

+   * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)

+   */

+  @Override

+  public void stop(BundleContext context_p) throws Exception {

+    __activator = null;

+  }

+

+  /**

+   * Get shared instance.

+   * @return

+   */

+  public static PatternActivator getDefault() {

+    return __activator;

+  }

+

+  /**

+   * Produce patterns pointed out by given ids path.

+   * @param fullId_p Either the absolute id of a library, or the absolute id of a pattern.

+   * @param forkJob_p Should production be executed in a job ? If true, there is no need for a specific progress monitor.

+   * @param progressMonitor_p A progress monitor to use in case of a synchronous production (can be null if no progress reporting is required).

+   * @return

+   */

+  public boolean producePatterns(

+    final String fullId_p, 

+    boolean forkJob_p, 

+    IProgressMonitor progressMonitor_p

+  ) {

+    boolean result = true;

+    // Lazy allocation.

+    if (_patternProducer == null) {

+      _patternProducer = new PatternProducer();

+    }

+    // Create progress runnable.

+    final PatternProducer patternProducer = _patternProducer;

+    IProgressRunnable producePattern = new IProgressRunnable() {

+      public String getReportingTitle() {

+        return Messages.PatternProducer_ProgressReporting_Title + fullId_p;

+      }

+      public boolean run(IProgressMonitor runnableProgressMonitor_p) {

+        return patternProducer.producePatterns(fullId_p, runnableProgressMonitor_p);

+      }

+    };

+    // Execute it.

+    if (forkJob_p) {

+      ProgressReporter.asyncExec(producePattern);

+    } else {

+      ProgressReporter.syncExec(producePattern, progressMonitor_p);

+    }

+    return result;

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/AbstractPatternGenerator.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/AbstractPatternGenerator.java
new file mode 100644
index 0000000..f3d6501
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/AbstractPatternGenerator.java
@@ -0,0 +1,444 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore;

+

+import java.util.List;

+

+import org.apache.log4j.Logger;

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.PatternHelper;

+import org.eclipse.egf.common.helper.StringHelper;

+import org.eclipse.egf.model.FactoryComponent;

+import org.eclipse.egf.pattern.Pattern;

+import org.eclipse.egf.pattern.PatternFactory;

+import org.eclipse.egf.pattern.ecore.PatternHandler.ProductionOptionsHandler;

+import org.eclipse.egf.pattern.production.GeneratedContentHelper;

+import org.eclipse.egf.pattern.production.template.TemplateHelper;

+import org.eclipse.egf.pattern.relations.ParameterRelation;

+import org.eclipse.egf.pde.EgfPdeActivator;

+import org.eclipse.emf.common.util.TreeIterator;

+import org.eclipse.emf.common.util.URI;

+import org.eclipse.emf.ecore.EClass;

+import org.eclipse.emf.ecore.EObject;

+import org.eclipse.emf.ecore.EOperation;

+import org.eclipse.emf.ecore.EPackage;

+import org.eclipse.emf.ecore.EParameter;

+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;

+

+

+/**

+ * Ecore pattern generator.

+ * @author brocard

+ */

+public abstract class AbstractPatternGenerator {

+  

+  /**

+   * Log4j reference logger.

+   */

+  private static final Logger __logger = Logger.getLogger(AbstractPatternGenerator.class.getPackage().getName());

+  

+  /**

+   * Ecore ecore file absolute path.

+   */

+  protected static final String ECORE_ECORE_FILE_ABSOLUTE_PATH = "/org.eclipse.emf.ecore/model/Ecore.ecore"; //$NON-NLS-1$

+  

+  /**

+   * Pattern ecore file absolute path.

+   */

+  protected static final String PATTERN_ECORE_FILE_RELATIVE_PATH = "/org.eclipse.egf.model/model/pattern.ecore"; //$NON-NLS-1$

+  

+  /**

+   * Pattern parent class name, that is 'Pattern'.

+   */

+  protected static final String PATTERN_PARENT_CLASS_NAME = "Pattern"; //$NON-NLS-1$

+  

+  /**

+   * Templates folder name.

+   */

+  protected static final String TEMPLATES_FOLDER_NAME = "/templates/"; //$NON-NLS-1$

+  

+  /**

+   * Generated templates sub-folder path.

+   */

+  protected static final String GENERATED_TEMPLATE_FOLDER_PATH = ICommonConstants.GENERATED_FOLDER_PATH; 

+

+  /**

+   * Find the class corresponding to given name in pointed ecore file.

+   * @param name_p

+   * @param ecoreURI_p

+   * @param resourceSet_p

+   * @return

+   */

+  protected static EClass getDependencyFromName(String name_p, String ecoreURI_p, ResourceSet resourceSet_p) {

+    EClass result = null;

+    // Preconditions.

+    if (name_p == null || ecoreURI_p == null || resourceSet_p == null) {

+      return result;

+    }

+    try {

+      URI patternURI = FileHelper.getFileFullUri(ecoreURI_p);

+      Resource parentResource = resourceSet_p.getResource(patternURI, true);

+      // Extract pattern as type from reloaded resource.

+      TreeIterator<EObject> content = parentResource.getAllContents();

+      while (content.hasNext() && result == null) {

+        EObject object = content.next();

+        if (object instanceof EClass) {

+          EClass class_ = (EClass) object;

+          // Retrieve the pattern EClass.

+          // Do not use something like '...'Package.Literals.'...' because it is not the instance stored in the resource.

+          // Otherwise, the persisted type URI leads to an invalid genmodel.

+          if (name_p.equals(class_.getName())) {

+            result = class_;

+          }

+        }

+      }

+    } catch (Exception exception_p) {

+      StringBuilder loggerMessage = new StringBuilder("AbstractPatternGenerator.getDependencyFromName(..) _ "); //$NON-NLS-1$

+      __logger.warn(loggerMessage.toString(), exception_p);

+    }

+    return result;

+  }

+

+  /**

+   * Get pattern parameters.<br>

+   * Ordered.

+   * @param resourceSet_p

+   * @return

+   */

+  protected List<ParameterRelation> getPatternParameters(ResourceSet resourceSet_p) {

+    return null;

+  }

+

+  /**

+   * Set pattern parent to identified one.<br>

+   * Default parent is {@link Pattern}.

+   * @param pattern_p The pattern that should be updated.

+   * @param parentClassName_p Parent class name, literally, or null if parent is to be reset.

+   * @param parentEcoreURI_p Parent class containing ecore uri, or null if parent is to be reset.

+   * @param resourceSet_p An existing one, or null if none is available.

+   */

+  public static void setPatternParent(Pattern pattern_p, String parentClassName_p, String parentEcoreURI_p, ResourceSet resourceSet_p) {

+    ResourceSet resourceSet = resourceSet_p;

+    // Precondition.

+    if (pattern_p == null) {

+      return;

+    }

+    // Create resource set if none given.

+    if (resourceSet == null) {

+      resourceSet = new ResourceSetImpl();

+    }

+    String parentClassName = parentClassName_p;

+    String parentEcoreURI = parentEcoreURI_p;

+    // Default parent is Pattern.

+    if (parentClassName == null || parentEcoreURI == null) {

+      parentClassName = PATTERN_PARENT_CLASS_NAME;

+      parentEcoreURI = PATTERN_ECORE_FILE_RELATIVE_PATH;

+    }

+    // Load pattern superclass.

+    EClass parent = getDependencyFromName(parentClassName, parentEcoreURI, resourceSet);

+    // Clear previous one, so that if no parent is found, then pattern parent is reset to none.

+    pattern_p.getESuperTypes().clear();

+    if (parent != null) {

+      // Add new one.

+      pattern_p.getESuperTypes().add(parent);

+    }

+  }

+

+  /**

+   * Generate pattern ecore file.

+   */

+  public boolean generateEcoreFile() {   

+    

+    // Create resource set for future use.

+    ResourceSet resourceSet = new ResourceSetImpl();

+

+    // Create new pattern structure.

+    Pattern newPattern = PatternFactory.eINSTANCE.createPattern();

+    // Set pattern id.

+    newPattern.setId(getPatternFullId());

+    // Set pattern superclass.

+    setPatternParent(newPattern, getParentClassName(), getParentEcoreURI(), resourceSet);

+

+    // Load pattern parameters.

+    List<ParameterRelation> parameters = getPatternParameters(resourceSet);

+    if (parameters != null) {

+      newPattern.getParameters().addAll(parameters);

+    }

+

+    // Create annotation handler.

+    AnnotationHandler annotationHandler = new AnnotationHandler();

+    // Add mandatory generate method to the new pattern.

+    EOperation generateOperation = addOperation(newPattern, PatternConstants.GENERATE_METHOD_NAME);

+    EParameter classLoaderParameter = EcoreFactory.eINSTANCE.createEParameter();

+    classLoaderParameter.setName(PatternConstants.GENERATE_METHOD_PARAMETER_NAME);

+    classLoaderParameter.setEType(EcorePackage.Literals.EJAVA_OBJECT);

+    generateOperation.getEParameters().add(classLoaderParameter);

+    

+    // Add mandatory generate pre-matching method to the new pattern.

+    addOperation(newPattern, PatternConstants.GENERATE_PRE_MATCHING_METHOD_NAME);

+    

+    // Add mandatory generate post-matching method to the new pattern.

+    addOperation(newPattern, PatternConstants.GENERATE_POST_MATCHING_METHOD_NAME);

+    

+    // Add mandatory generate header method to the new pattern.

+    EOperation generateHeader = addOperation(newPattern, PatternConstants.GENERATE_HEADER_METHOD_NAME);

+    annotationHandler.addUidAnnotation(generateHeader);

+    

+    // Add mandatory generate footer method to the new pattern.

+    EOperation generateFooter = addOperation(newPattern, PatternConstants.GENERATE_FOOTER_METHOD_NAME);

+    annotationHandler.addUidAnnotation(generateFooter);

+

+    // Fill pattern with specific content.

+    fillPattern(newPattern, annotationHandler, generateOperation);

+

+    String patternContainingPluginId = getPatternContainingPluginId();

+    // Initialize both pattern code and java code annotations for all pattern operations, excluding the generate one.

+    FactoryComponent containingFc = EgfPdeActivator.getDefault().getFactoryComponentForPluginId(patternContainingPluginId);

+    computeOperationsAnnotations(

+      newPattern, 

+      containingFc == null ? patternContainingPluginId : containingFc.getId(), 

+      annotationHandler

+    );

+

+    // Write pattern structure to ecore file.

+    return writePatternModelToFile(

+      newPattern, 

+      getPatternModelRelativePath(

+        patternContainingPluginId, 

+        PatternHelper.deresolveId(newPattern.getId()).getValue()

+      )

+    );

+    

+  }

+

+  /**

+   * (Re)Compute annotations for all pattern operations.

+   * @param pattern_p

+   * @param fcId_p

+   * @param annotationHandler_p

+   */

+  public static void computeOperationsAnnotations(Pattern pattern_p, String fcId_p, AnnotationHandler annotationHandler_p) {

+    // Precondition.

+    if (pattern_p == null) {

+      return;

+    }

+    // Get annotation handler.

+    AnnotationHandler handler = annotationHandler_p;

+    if (handler == null) {

+      handler = new AnnotationHandler();

+    }

+    // Get pattern name.

+    String patternShortId = PatternHelper.deresolveId(pattern_p.getId()).getValue();

+    // Cycle through pattern operations :

+    // 1) Remove all existing annotations if any.

+    // 2) Add pattern code annotation that reads the corresponding template file.

+    // 2bis) Or replace its content with respect to the new pattern properties.

+    List<EOperation> operations = pattern_p.getEOperations();

+    for (EOperation operation : operations) {

+      String templateRelativePath = TemplateHelper.getTemplateRelativePath(

+        patternShortId, 

+        fcId_p, 

+        operation.getName(), 

+        handler.getUid(operation)

+      );

+      if (templateRelativePath != null) {

+        if (handler.hasPatternCode(operation) == false) {

+          // Add read template file pattern code annotation.

+          handler.addReadFilePatternCode(operation, templateRelativePath);

+        }

+      }

+    }

+    // Now translate pattern code annotations to java code annotations.

+    handler.translateAnnotations(operations);

+  }

+

+  /**

+   * Compute and add production annotation for given pattern.

+   * @param pattern_p The pattern needing to be tagged with a production annotation.

+   * @param handler_p The production options handler, containing the annotation value.

+   * @param annotationHandler_p A possibly existing annotation handler, null if none to provide at call time.

+   */

+  public static void computeProductionAnnotation(Pattern pattern_p, ProductionOptionsHandler handler_p, AnnotationHandler annotationHandler_p) {

+    // Get annotation handler.

+    AnnotationHandler annotationHandler = annotationHandler_p;

+    if (annotationHandler == null) {

+      annotationHandler = new AnnotationHandler();

+    }

+    // Add/replace production annotation.

+    boolean successful = annotationHandler.addProductionAnnotation(pattern_p, handler_p);

+    if (successful == false) {

+      __logger.warn(

+        new StringBuilder("AbstractPatternGenerator.computeProductionAnnotation(..) _ ") //$NON-NLS-1$

+          .append("Could not set production annotation for pattern ") //$NON-NLS-1$

+          .append(pattern_p != null ? pattern_p.getName() : null)

+          .toString()

+      );

+    }

+  }

+

+  /**

+   * Get pattern model relative path.

+   * @param containerId_p either the factory component or the plug-in id, depending on the caller.<br>

+   *          It is up to the caller to make sure that given plug-in id (if so) is up-to-date (for instance after a refactoring).

+   * @param patternId_p

+   * @return null if one of the given parameter is null.

+   */

+  public static String getPatternModelRelativePath(String containerId_p, String patternId_p) {

+    // Preconditions.

+    if (containerId_p == null || patternId_p == null) {

+      return null;

+    }

+    return 

+      new StringBuilder(containerId_p)

+        .append(PatternConstants.PATTERN_MODEL_FOLDER)

+        .append(StringHelper.replaceNonWordCharactersWithDot(patternId_p))

+        .append(ICommonConstants.DOT_CHARACTER)

+        .append(PatternConstants.PATTERN_MODEL_FILE_EXTENSION)

+        .toString();

+  }

+

+  /**

+   * Write pattern model to file.

+   * @param pattern_p

+   * @param fileRelativePath_p

+   * @return true if successfully written, false otherwise.

+   */

+  static boolean writePatternModelToFile(Pattern pattern_p, String fileRelativePath_p) {

+    boolean result = false;

+    // Check if file is writable first.

+    boolean writable = FileHelper.makeFileWritable(fileRelativePath_p);

+    // File was not granted rights for modification (either by the system or by the user), stop here.

+    if (writable == false) {

+      return result;

+    }

+    // Create package that contains the pattern.

+    EPackage container = EcoreFactory.eINSTANCE.createEPackage();

+    container.setName(GeneratedContentHelper.getPatternPackageName(pattern_p));

+    container.setNsURI(GeneratedContentHelper.getPatternPackageNsURI(pattern_p));

+    container.setNsPrefix(GeneratedContentHelper.getPatternPackageNsPrefix(pattern_p));

+    container.getEClassifiers().add(pattern_p);

+    // Write pattern structure to ecore file.

+    try {

+      // Get file full URI.

+      URI fileFullUri = FileHelper.getFileFullUri(fileRelativePath_p);

+      ResourceSet resourceSet = new ResourceSetImpl();

+      // Create associated resource.

+      Resource patternResource = resourceSet.createResource(fileFullUri);

+      patternResource.getContents().add(container);

+      patternResource.save(null);

+      result = true;

+    } catch (Exception exception_p) {

+      result = false;

+      StringBuilder loggerMessage = new StringBuilder("AbstractPatternGenerator.writePatternModelToFile(..) _ "); //$NON-NLS-1$

+      __logger.warn(loggerMessage.toString(), exception_p);

+    }

+    return result;

+  }

+

+  /**

+   * Add a new operation to handled pattern.

+   * @param operationName_p

+   * @return The annotation that will contain the resulting method contents (as defined by the pattern annotation grammar).<br>

+   *         Empty at this time.

+   */

+  public static EOperation addOperation(Pattern pattern_p, String operationName_p) {

+    EOperation newOperation = EcoreFactory.eINSTANCE.createEOperation();

+    newOperation.setName(operationName_p);

+    newOperation.setEType(EcorePackage.eINSTANCE.getEString());

+    pattern_p.getEOperations().add(newOperation);

+    return newOperation;

+  }

+

+  /**

+   * Remove operation from given pattern.

+   * @param pattern_p

+   * @param operation_p

+   */

+  public static void removeOperation(Pattern pattern_p, EOperation operation_p) {

+    if (pattern_p != null && operation_p != null) {

+      pattern_p.getEOperations().remove(operation_p);

+    }

+  }

+

+  /**

+   * Get pattern short id.

+   * @param pattern_p

+   * @return

+   */

+  protected String getPatternShortId(Pattern pattern_p) {

+    String result = null;

+    // Precondition.

+    if (pattern_p == null) {

+      return result;

+    }

+    result = PatternHelper.deresolveId(pattern_p.getId()).getValue();

+    return result;

+  }

+

+  /**

+   * Get template relative path from operation name.

+   * @param patternShortId_p

+   * @param operationName_p

+   * @param operationId_p

+   * @return

+   */

+  protected String getTemplateRelativePath(String patternShortId_p, String operationName_p, String operationId_p) {

+    return TemplateHelper.getTemplateRelativePath(

+      patternShortId_p, 

+      getPatternContainingPluginId(), 

+      operationName_p, 

+      operationId_p

+    );

+  }

+

+  /**

+   * Fill newly created pattern with expected content.<br>

+   * The given operation is the 'generate' one, as defined by the pattern metamodel.

+   * @param newPattern_p

+   * @param handler_p

+   * @param generateContent_p

+   */

+  protected abstract void fillPattern(Pattern newPattern_p, AnnotationHandler handler_p, EOperation generate_p);

+

+  /**

+   * Get parent parent class name.

+   * @return

+   */

+  protected String getParentClassName() {

+    return null;

+  }

+

+  /**

+   * Get pattern parent class ecore URI.

+   * @return

+   */

+  protected String getParentEcoreURI() {

+    return null;

+  }

+

+  /**

+   * Get pattern containing plug-in id.

+   * @return

+   */

+  protected abstract String getPatternContainingPluginId();

+

+  /**

+   * Get pattern full id.

+   * @return

+   */

+  protected abstract String getPatternFullId();

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/AnnotationHandler.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/AnnotationHandler.java
new file mode 100644
index 0000000..a243c7b
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/AnnotationHandler.java
@@ -0,0 +1,997 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore;

+

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.Iterator;

+import java.util.List;

+

+import org.antlr.runtime.ANTLRStringStream;

+import org.antlr.runtime.CommonTokenStream;

+import org.antlr.runtime.RecognitionException;

+import org.antlr.runtime.tree.CommonTree;

+import org.antlr.runtime.tree.Tree;

+import org.apache.log4j.Logger;

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.helper.IDGeneratorHelper;

+import org.eclipse.egf.common.helper.StringHelper;

+import org.eclipse.egf.common.misc.Couple;

+import org.eclipse.egf.pattern.Pattern;

+import org.eclipse.egf.pattern.ecore.PatternHandler.ProductionOptionsHandler;

+import org.eclipse.egf.pattern.ecore.grammar.PatternLanguageLexer;

+import org.eclipse.egf.pattern.ecore.grammar.PatternLanguageParser;

+import org.eclipse.egf.pattern.production.jet.JETConstants;

+import org.eclipse.emf.common.util.EMap;

+import org.eclipse.emf.ecore.EAnnotation;

+import org.eclipse.emf.ecore.EOperation;

+import org.eclipse.emf.ecore.EParameter;

+import org.eclipse.emf.ecore.EcoreFactory;

+

+

+/**

+ * The annotation handler translates a pattern methods annotations to java code annotations.<br>

+ * It also provides with a parsing of the methods annotations.

+ * @author brocard

+ */

+public class AnnotationHandler {

+  

+  /**

+   * Log4j reference logger.

+   */

+  private static final Logger __logger = Logger.getLogger(AnnotationHandler.class.getPackage().getName());

+  

+  /**

+   * Super method call prefix.

+   */

+  protected static final String JAVA_CODE_SUPER_CALL_PREFIX = "super."; //$NON-NLS-1$

+  

+  /**

+   * Read file method call prefix.

+   */

+  protected static final String JAVA_CODE_READ_FILE_CALL_PREFIX = "org.eclipse.egf.pattern.production.template.TemplateHelper.readTemplateFile"; //$NON-NLS-1$

+  

+  /**

+   * Create string builder.

+   */

+  protected static final String JAVA_CODE_CREATE_STRING_BUILDER = "StringBuilder builder = new StringBuilder();"; //$NON-NLS-1$

+  

+  /**

+   * Append to string builder.

+   */

+  protected static final String JAVA_CODE_APPEND_TO_STRING_BUILDER = "builder.append"; //$NON-NLS-1$

+  

+  /**

+   * Return string builder result.

+   */

+  protected static final String JAVA_CODE_GET_STRING_BUILDER_RESULT = "return builder.toString();"; //$NON-NLS-1$

+  

+  /**

+   * Operation annotation body.

+   */

+  protected static final String OPERATION_ANNOTATION_BODY = "body"; //$NON-NLS-1$

+  

+  /**

+   * UID annotation source.

+   */

+  protected static final String UID_ANNOTATION_SOURCE = "http://www.eclipse.org/egf/1.0.0/uid"; //$NON-NLS-1$

+  

+  /**

+   * Java code annotation source.

+   */

+  protected static final String JAVA_CODE_ANNOTATION_SOURCE = "http://www.eclipse.org/emf/2002/GenModel"; //$NON-NLS-1$

+  

+  /**

+   * Pattern code annotation source.

+   */

+  public static final String PATTERN_CODE_ANNOTATION_SOURCE = "http://www.eclipse.org/egf/1.0.0/Pattern"; //$NON-NLS-1$

+  

+  /**

+   * Pattern production annotation source.

+   */

+  public static final String PATTERN_PRODUCTION_ANNOTATION_SOURCE = "http://www.eclipse.org/egf/1.0.0/Pattern/production"; //$NON-NLS-1$

+  

+  /**

+   * Pattern production path annotation body.

+   */

+  public static final String PATTERN_PRODUCTION_ANNOTATION_BODY_PATH = "Path"; //$NON-NLS-1$

+  

+  /**

+   * Pattern production compilation annotation body.

+   */

+  public static final String PATTERN_PRODUCTION_ANNOTATION_BODY_COMPILATION = "Compilation"; //$NON-NLS-1$

+  

+  /**

+   * Pattern production buffer modification annotation body.

+   */

+  public static final String PATTERN_PRODUCTION_ANNOTATION_BODY_BUFFER_MODIFICATION = "BufferModification"; //$NON-NLS-1$

+  

+  /**

+   * Pattern method id prefix.

+   */

+  protected static final String PATTERN_METHOD_ID_PREFIX = "PatternMethod"; //$NON-NLS-1$

+

+  /**

+   * Get abstract syntax tree out of given pattern code.

+   * @param patternCode_p

+   * @return

+   */

+  protected CommonTree getTree(String patternCode_p) {

+    CommonTree result = null;

+    // Try and get the abstract syntax tree out of the pattern code.

+    PatternLanguageLexer lexer = new PatternLanguageLexer(new ANTLRStringStream(patternCode_p));

+    CommonTokenStream tokens = new CommonTokenStream(lexer);

+    PatternLanguageParser parser = new PatternLanguageParser(tokens);

+    try {

+      // Parse pattern code and get the tree.

+      result = (CommonTree) parser.call().getTree();

+    } catch (RecognitionException exception_p) {

+      StringBuilder loggerMessage = new StringBuilder("AnnotationHandler.getTree(..) _ "); //$NON-NLS-1$

+      __logger.warn(loggerMessage.toString(), exception_p);

+    }

+    return result;

+  }

+

+  /**

+   * Get ordered list of pattern code actions for given pattern operation.

+   * @param operation_p

+   * @return List of (action, parameter) couples.

+   */

+  public List<Couple<String, String>> getOrderedActionsFor(EOperation operation_p) {

+    List<Couple<String, String>> actions = new ArrayList<Couple<String, String>>(0);

+    // Precondition.

+    if (null == operation_p) {

+      return actions;

+    }

+    // Get pattern code.

+    String patternCode = getPatternCode(operation_p);

+    // Precondition.

+    if (null == patternCode) {

+      return actions;

+    }

+    CommonTree tree = getTree(patternCode);

+    // Explore the actions tree, and fill given list accordingly (as the tree is being explored).

+    explore(tree, actions);

+    return actions;

+  }

+

+  /**

+   * Get pattern IDs that are called through this operation.<br>

+   * Only applicable to the generate method.

+   * @param operation_p

+   * @return An empty list of String if given method is null or is not the generate method or no external pattern is called.

+   * A list of called patterns full IDs otherwise.

+   */

+  @SuppressWarnings("unchecked")

+  public List<String> getCalledPatternIDs(EOperation operation_p) {

+    // Precondition.

+    if (null == operation_p) {

+      return Collections.EMPTY_LIST;

+    }

+    List<Couple<String, String>> orderedActions = getOrderedActionsFor(operation_p);

+    List<String> result = new ArrayList<String>(0);

+    for (Couple<String, String> action : orderedActions) {

+      // Get call to another pattern.

+      if (PatternConstants.PC_TAG_PATTERN.equals(action.getKey())) {

+        result.add(action.getValue());

+      }

+    }

+    return result;

+  }

+

+  /**

+   * Replace old parameter value with new one, everywhere it is used in given actions list.

+   * @param oldParameterValue_p

+   * @param newParameterValue_p As a result, given actions list remains unmodified, but its contained actions are (unless no modification happened).

+   */

+  public void replaceParameter(String oldParameterValue_p, String newParameterValue_p, List<Couple<String, String>> actions_p) {

+    // Preconditions.

+    if ((null == actions_p) || (null == oldParameterValue_p) || (null == newParameterValue_p)) {

+      return;

+    }

+    // Iterate through actions.

+    for (Couple<String, String> action : actions_p) {

+      // Replace old value with new one.

+      if (oldParameterValue_p.equals(action.getValue())) {

+        action.setValue(newParameterValue_p);

+      }

+    }

+  }

+

+  /**

+   * Remove actions using given parameter from given actions list.

+   * @param parameterValue_p

+   * @param actions_p

+   * @return {@link List} of removed actions.

+   * @deprecated

+   */

+  public List<Couple<String, String>> removeActionsFor(String parameterValue_p, List<Couple<String, String>> actions_p) {

+    if ((null == parameterValue_p) || (null == actions_p) || actions_p.isEmpty()) {

+      return null;

+    }

+    // Clone actions list.

+    List<Couple<String, String>> clonedActions = new ArrayList<Couple<String, String>>(0);

+    clonedActions.addAll(actions_p);

+    // Iterate through actions.

+    for (Couple<String, String> action : clonedActions) {

+      // If parameter value matches, then remove action from given list.

+      if (parameterValue_p.equals(action.getValue())) {

+        actions_p.remove(action);

+      }

+    }

+    // Retain removed actions.

+    clonedActions.removeAll(actions_p);

+    return clonedActions;

+  }

+

+  /**

+   * Recompute pattern code annotation for given method using given actions.<br>

+   * As a result, java code annotation is removed, and is to be recomputed.

+   * @param operation_p

+   * @param actions_p

+   */

+  public void recomputeAnnotationFromActions(EOperation operation_p, List<Couple<String, String>> actions_p) {

+    // Preconditions.

+    if ((null == operation_p) || (null == actions_p)) {

+      return;

+    }

+    // Clear recomputed annotations.

+    List<EAnnotation> keptAnnotations = Collections.singletonList(operation_p.getEAnnotation(UID_ANNOTATION_SOURCE));

+    operation_p.getEAnnotations().retainAll(keptAnnotations);

+    // Reconstruct pattern code.

+    for (Couple<String, String> action : actions_p) {

+      String actionType = action.getKey();

+      String actionParameter = action.getValue();

+      if (PatternConstants.PC_TAG_CALL.equals(actionType)) {

+        // Call to a method call.

+        addCallMethodPatternCode(operation_p, actionParameter);

+      } else if (PatternConstants.PC_TAG_PATTERN.equals(actionType)) {

+        // Call to another pattern.

+        addGenerateOtherPatternPatternCode(operation_p, actionParameter);

+      } else if (PatternConstants.PC_TAG_READ.equals(actionType)) {

+        // Call to read template file.

+        addReadFilePatternCode(operation_p, actionParameter);

+      } else if (PatternConstants.PC_TAG_SUPER.equals(actionType)) {

+        // Call to super method.

+        addSuperMethodCallPatternCode(operation_p, actionParameter);

+      }

+    }

+  }

+

+  /**

+   * Add UID annotation to given operation.

+   * @param operation_p

+   * @return String, the UID set for this operation, null if given operation is null.

+   */

+  public String addUidAnnotation(EOperation operation_p) {

+    String result = null;

+    // Precondition.

+    if (null == operation_p) {

+      return result;

+    }

+    // Get existing one, if any.

+    EAnnotation annotation = operation_p.getEAnnotation(UID_ANNOTATION_SOURCE);

+    if (null == annotation) {

+      annotation = EcoreFactory.eINSTANCE.createEAnnotation();

+      // Add it to operation.

+      operation_p.getEAnnotations().add(annotation);

+      annotation.setSource(UID_ANNOTATION_SOURCE);

+    }

+    // Create and set UID.

+    result = IDGeneratorHelper.generatePrefixUID(PATTERN_METHOD_ID_PREFIX);

+    annotation.getDetails().put(OPERATION_ANNOTATION_BODY, result);

+    return result;

+  }

+

+  /**

+   * Add/replace pattern production annotation based on given production handler values.

+   * @param pattern_p

+   * @param productionHandler_p

+   * @return

+   */

+  public boolean addProductionAnnotation(Pattern pattern_p, ProductionOptionsHandler productionHandler_p) {

+    boolean result = false;

+    // Preconditions.

+    if ((null == pattern_p) || (null == productionHandler_p)) {

+      return result;

+    }

+    // Get annotation.

+    EAnnotation annotation = pattern_p.getEAnnotation(PATTERN_PRODUCTION_ANNOTATION_SOURCE);

+    // None existed, create a new one.

+    if (null == annotation) {

+      annotation = EcoreFactory.eINSTANCE.createEAnnotation();

+      annotation.setSource(PATTERN_PRODUCTION_ANNOTATION_SOURCE);

+      // Add it to pattern.

+      pattern_p.getEAnnotations().add(annotation);

+    }

+    // Add/update the different production options.

+    // The produced template relative path.

+    EMap<String, String> details = annotation.getDetails();

+    details.put(PATTERN_PRODUCTION_ANNOTATION_BODY_PATH, productionHandler_p.getPatternTemplatePath());

+    // The compilation flag.

+    details.put(PATTERN_PRODUCTION_ANNOTATION_BODY_COMPILATION, Boolean.toString(productionHandler_p.shouldCompileTemplate()));

+    // The buffer modification flag.

+    details.put(PATTERN_PRODUCTION_ANNOTATION_BODY_BUFFER_MODIFICATION, Boolean.toString(productionHandler_p.shouldModifyBuffer()));

+    result = true;

+    return result;

+  }

+

+  /**

+   * Remove production annotation from given pattern, if any.

+   * @param pattern_p

+   * @return Removed annotation, or null if given pattern is null or is not containing such an annotation.

+   */

+  public EAnnotation removeProductionAnnotation(Pattern pattern_p) {

+    EAnnotation result = null;

+    // Precondition.

+    if (null == pattern_p) {

+      return result;

+    }

+    result = pattern_p.getEAnnotation(PATTERN_PRODUCTION_ANNOTATION_SOURCE);

+    if (null != result) {

+      pattern_p.getEAnnotations().remove(result);

+    }

+    return result;

+  }

+

+  /**

+   * Get operation UID.

+   * @param operation_p

+   * @return null if given operation is null.

+   */

+  public String getUid(EOperation operation_p) {

+    String result = null;

+    // Precondition.

+    if (null == operation_p) {

+      return result;

+    }

+    // Get UID, if any.

+    EAnnotation uidAnnotation = operation_p.getEAnnotation(UID_ANNOTATION_SOURCE);

+    if (null != uidAnnotation) {

+      result = uidAnnotation.getDetails().get(OPERATION_ANNOTATION_BODY);

+    }

+    return result;

+  }

+

+  /**

+   * Get a couple composed of the top action (and its parameter) of given tree.

+   * @param tree_p

+   * @return Key = action name, Value = parameter.

+   */

+  protected Couple<String, String> getActionAndParameter(Tree tree_p) {

+    // Precondition.

+    if (null == tree_p) {

+      return null;

+    }

+    // Get action type (ie action name).

+    String actionType = tree_p.getText();

+    // Get action parameter, if any.

+    String actionParameter = getFirstChild(tree_p);

+    return new Couple<String, String>(actionType, actionParameter);

+  }

+

+  /**

+   * Explore current tree level, and fill given pattern code actions list accordingly.

+   * @param tree_p

+   * @param actions_p

+   */

+  protected void explore(Tree tree_p, List<Couple<String, String>> actions_p) {

+    Couple<String, String> currentAction = getActionAndParameter(tree_p);

+    // Precondition.

+    if (null == currentAction) {

+      return;

+    }

+    String actionType = currentAction.getKey();

+    if (PatternConstants.PC_TAG_CALL.equals(actionType) || PatternConstants.PC_TAG_SUPER.equals(actionType) || PatternConstants.PC_TAG_READ.equals(actionType)

+        || PatternConstants.PC_TAG_PATTERN.equals(actionType)) { // Action type must meet the pattern code grammar definition.

+      actions_p.add(currentAction);

+    } else { // If current node is not one of the looked for word, go-on with children.

+      // Cycle through children.

+      int childCount = tree_p.getChildCount();

+      // Explore first-level children.

+      for (int i = 0; i < childCount; i++) {

+        explore(tree_p.getChild(i), actions_p);

+      }

+    }

+  }

+

+  /**

+   * Translate annotations from pattern code to java code for given pattern operations.

+   * @param operations_p

+   * @return true if successful, false otherwise.

+   */

+  public boolean translateAnnotations(List<EOperation> operations_p) {

+    boolean result = true;

+    // Preconditions.

+    if ((null == operations_p) || operations_p.isEmpty()) {

+      return result;

+    }

+    // Iterate over given operations.

+    for (EOperation operation : operations_p) {

+      result &= doTranslateAnnotation(operation);

+    }

+    return result;

+  }

+

+  /**

+   * Is given operation referencing pattern code ?

+   * @param operation_p

+   * @return

+   */

+  public boolean hasPatternCode(EOperation operation_p) {

+    return (null != getPatternCode(operation_p));

+  }

+

+  /**

+   * Do translate annotation for given operation.

+   * @param operation_p

+   * @return

+   */

+  protected boolean doTranslateAnnotation(EOperation operation_p) {

+    // By default, no translation is a successful one.

+    boolean result = true;

+    // Get pattern code.

+    String patternCode = getPatternCode(operation_p);

+    // Precondition.

+    if (null == patternCode) {

+      return result;

+    }

+    // Initialize java code.

+    initializeJavaCode(operation_p);

+    // Try and get the abstract syntax tree out of the pattern code.

+    CommonTree tree = getTree(patternCode);

+    if (null != tree) {

+      exploreAndTranslate(tree, operation_p);

+    }

+    // Always try to return a correct piece of code.

+    finalizeJavaCode(operation_p);

+    return result;

+  }

+

+  /**

+   * Explore annotation abstract syntax tree and translate accordingly.

+   * @param tree_p

+   * @param operation_p

+   */

+  protected void exploreAndTranslate(Tree tree_p, EOperation operation_p) {

+    Couple<String, String> action = getActionAndParameter(tree_p);

+    // Precondition.

+    if (null == action) {

+      return;

+    }

+    // Get action type (ie action name).

+    String actionType = action.getKey();

+    // Get action parameter, if any.

+    String actionParameter = action.getValue();

+    if (PatternConstants.PC_TAG_CALL.equals(actionType)) { // CALL code ?

+      addCallMethodJavaCode(operation_p, actionParameter);

+    } else if (PatternConstants.PC_TAG_SUPER.equals(actionType)) { // SUPER code ?

+      addSuperMethodCallJavaCode(operation_p, actionParameter);

+    } else if (PatternConstants.PC_TAG_READ.equals(actionType)) { // READ code ?

+      addReadFileJavaCode(operation_p, actionParameter);

+    } else if (PatternConstants.PC_TAG_PATTERN.equals(actionType)) {

+      addGenerateOtherPatternJavaCode(operation_p, actionParameter);

+    } else { // If current node is not one of the looked for word, go-on with children.

+      int childCount = tree_p.getChildCount();

+      // Explore first-level children.

+      for (int i = 0; i < childCount; i++) {

+        exploreAndTranslate(tree_p.getChild(i), operation_p);

+      }

+    }

+  }

+

+  /**

+   * Get first child of given tree as a string.

+   * @param tree_p

+   * @return null if none could be found.

+   */

+  protected String getFirstChild(Tree tree_p) {

+    String result = null;

+    if ((null != tree_p) && (0 < tree_p.getChildCount())) {

+      result = tree_p.getChild(0).getText();

+    }

+    return result;

+  }

+

+  /**

+   * Get pattern code for given operation.

+   * @param operation_p

+   * @return null if no code could be found.

+   */

+  protected String getPatternCode(EOperation operation_p) {

+    // Do not force creation, if no pattern code annotation could be found.

+    EAnnotation patternCodeAnnotation = getOrCreatePatternCodeAnnotation(operation_p, false);

+    // Precondition.

+    if (null == patternCodeAnnotation) {

+      return null;

+    }

+    // Get existing pattern code.

+    return patternCodeAnnotation.getDetails().get(OPERATION_ANNOTATION_BODY);

+  }

+

+  /**

+   * Initialize java code for given operation.<br>

+   * It does create a new java code annotation, and add string builder creation code.

+   * @param operation_p

+   */

+  protected void initializeJavaCode(EOperation operation_p) {

+    // Precondition.

+    if (null == operation_p) {

+      return;

+    }

+    // Done through a code appender.

+    new UnbufferedJavaCodeAppender() {

+      /**

+       * @see org.eclipse.egf.pattern.ecore.AnnotationHandler.JavaCodeAppender#getCodeAnnotation(org.eclipse.emf.ecore.EOperation)

+       */

+      @Override

+      protected EAnnotation getCodeAnnotation(EOperation operation) {

+        // First of all, remove possibly existing java annotation.

+        EAnnotation javaCodeAnnotation = operation.getEAnnotation(JAVA_CODE_ANNOTATION_SOURCE);

+        operation.getEAnnotations().remove(javaCodeAnnotation);

+        // Then behave as expected.

+        return super.getCodeAnnotation(operation);

+      }

+

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Add string builder creation code.

+        existingCode_p.append(JAVA_CODE_CREATE_STRING_BUILDER);

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Finalize java code for given operation.<br>

+   * Adds string builder return code.

+   * @param operation_p

+   */

+  protected void finalizeJavaCode(EOperation operation_p) {

+    // Precondition.

+    if (null == operation_p) {

+      return;

+    }

+    // Done through a code appender.

+    new UnbufferedJavaCodeAppender() {

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Add string builder return result code.

+        existingCode_p.append(JAVA_CODE_GET_STRING_BUILDER_RESULT);

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Add generate identified pattern (pattern code) for given operation and pattern full id.

+   * @param operation_p

+   * @param patternFullId_p

+   */

+  public void addGenerateOtherPatternPatternCode(EOperation operation_p, final String patternFullId_p) {

+    // Preconditions.

+    if ((null == operation_p) || (null == patternFullId_p)) {

+      return;

+    }

+    // Done through a code appender.

+    new PatternCodeAppender() {

+      @Override

+      protected String getOperationName() {

+        return PatternConstants.PC_TAG_PATTERN;

+      }

+

+      @Override

+      protected String getParameter() {

+        return patternFullId_p;

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * TODO Guillaume<br>

+   * Specific to JET templates.<br>

+   * Add generate identified pattern (java code) for given operation and pattern full id.

+   * @param operation_p

+   * @param patternFullId_p

+   */

+  protected void addGenerateOtherPatternJavaCode(EOperation operation_p, final String patternFullId_p) {

+    // Precondition.

+    if ((null == operation_p) || (null == patternFullId_p)) {

+      return;

+    }

+    // Add JET start mark-up.

+    new JavaCodeAppender() {

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Very specific to JET.

+        existingCode_p.append(JETConstants.EXTERNAL_USE_JET_MARKUP_START);

+      }

+    }.appendCode(operation_p);

+    // Done through a code appender.

+    new JavaCodeAppender() {

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Resulting code looks like : "<%stringBuffer.append(com.thalesgroup.*.PatternExecutionHelper.invokePattern("pattern full id", argument));%>"

+        // Specific to JET for stringBuffer is a JET variable.

+        existingCode_p.append(ICommonConstants.QUOTE_CHARACTER).append("stringBuffer.append").append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER); //$NON-NLS-1$

+        existingCode_p.append(getCallOtherPatternTemplateCode(patternFullId_p)).append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER);

+        existingCode_p.append(ICommonConstants.SEMICOLON_CHARACTER).append(ICommonConstants.QUOTE_CHARACTER);

+      }

+    }.appendCode(operation_p);

+    // Add JET end mark-up.

+    new JavaCodeAppender() {

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Very specific to JET.

+        existingCode_p.append(JETConstants.EXTERNAL_USE_JET_MARKUP_END);

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * TODO Guillaume<br>

+   * Specific to JET templates.<br>

+   * Get call to another pattern template code.

+   * @param patternFullId_p The pattern to call full id.

+   * @return

+   */

+  protected String getCallOtherPatternTemplateCode(String patternFullId_p) {

+    // Specific to JET for argument is a JET variable.

+    return StringHelper

+        .formatMessage(

+                       "org.eclipse.egf.pattern.execution.PatternExecutionHelper.invokePattern(\\\"{0}\\\", argument)", new Object[] { patternFullId_p }); //$NON-NLS-1$

+  }

+

+  /**

+   * Add read file (pattern code) for given operation and file relative path.

+   * @param operation_p

+   * @param fileRelativePath_p

+   */

+  public void addReadFilePatternCode(EOperation operation_p, final String fileRelativePath_p) {

+    // Preconditions.

+    if ((null == operation_p) || (null == fileRelativePath_p)) {

+      return;

+    }

+    // Done through a code appender.

+    new PatternCodeAppender() {

+      @Override

+      protected String getOperationName() {

+        return PatternConstants.PC_TAG_READ;

+      }

+

+      @Override

+      protected String getParameter() {

+        return fileRelativePath_p;

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Add read file (java code) for given operation and file relative path.

+   * @param operation_p

+   * @param fileRelativePath_p

+   */

+  protected void addReadFileJavaCode(EOperation operation_p, final String fileRelativePath_p) {

+    // Preconditions.

+    if ((null == operation_p) || (null == fileRelativePath_p)) {

+      return;

+    }

+    // Done through a code appender.

+    new JavaCodeAppender() {

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Resulting code looks like : 'com.thalesgroup.*.TemplateHelper.readTemplateFile("fileRelativePath");'

+        existingCode_p.append(JAVA_CODE_READ_FILE_CALL_PREFIX).append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+        existingCode_p.append(ICommonConstants.QUOTE_CHARACTER).append(fileRelativePath_p).append(ICommonConstants.QUOTE_CHARACTER);

+        existingCode_p.append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER);

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Add call method (pattern code) for given operation and method name.

+   * @param operation_p

+   * @param methodName_p

+   */

+  public void addCallMethodPatternCode(EOperation operation_p, final String methodName_p) {

+    // Precondition.

+    if ((null == operation_p) || (null == methodName_p)) {

+      return;

+    }

+    // Done through a code appender.

+    new PatternCodeAppender() {

+      @Override

+      protected String getOperationName() {

+        return PatternConstants.PC_TAG_CALL;

+      }

+

+      @Override

+      protected String getParameter() {

+        return methodName_p;

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Add call method (java code) for given operation and method name.

+   * @param operation_p

+   * @param methodName_p

+   */

+  protected void addCallMethodJavaCode(EOperation operation_p, final String methodName_p) {

+    // Preconditions.

+    if ((null == operation_p) || (null == methodName_p)) {

+      return;

+    }

+    // Done through a code appender.

+    new JavaCodeAppender() {

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Resulting java code looks like : 'myMethodName();'

+        existingCode_p.append(methodName_p).append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER).append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER);

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Add call to super method (pattern code) for given operation and method name.

+   * @param operation_p

+   * @param methodName_p

+   */

+  public void addSuperMethodCallPatternCode(EOperation operation_p, final String methodName_p) {

+    // Precondition.

+    if (null == operation_p) {

+      return;

+    }

+    // Done through a code appender.

+    new PatternCodeAppender() {

+      @Override

+      protected String getOperationName() {

+        return PatternConstants.PC_TAG_SUPER;

+      }

+

+      @Override

+      protected String getParameter() {

+        return methodName_p;

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Add call to super method (java code) for given operation and method name.

+   * @param operation_p

+   * @param methodName_p Can be null, the given operation name is used instead.

+   */

+  protected void addSuperMethodCallJavaCode(EOperation operation_p, String methodName_p) {

+    // Precondition.

+    if (null == operation_p) {

+      return;

+    }

+    // Get method name.

+    final String[] methodName = new String[] { methodName_p };

+    // By default, there is no parameters to the super call.

+    final List<EParameter> parametersList = new ArrayList<EParameter>(0);

+    // No method name, make a super call to override method.

+    if (null == methodName_p) {

+      // Method name is the same as currently handled operation.

+      methodName[0] = operation_p.getName();

+      // And parameters are similar too.

+      parametersList.addAll(operation_p.getEParameters());

+    }

+    // Done through a code appender.

+    new JavaCodeAppender() {

+      @Override

+      protected void appendNewOperation(StringBuilder existingCode_p) {

+        // Resulting java code looks like : 'super.myMethodName(methodParameters);'

+        existingCode_p.append(JAVA_CODE_SUPER_CALL_PREFIX).append(methodName[0]).append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+        // Add parameters, super parameters should be the same, so there should be no issue there.

+        for (Iterator<EParameter> parameters = parametersList.iterator(); parameters.hasNext();) {

+          existingCode_p.append(parameters.next().getName());

+          // Append comma after parameter if there is a following parameter.

+          if (parameters.hasNext()) {

+            existingCode_p.append(ICommonConstants.COMMA_CHARACTER);

+          }

+        }

+        existingCode_p.append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER);

+      }

+    }.appendCode(operation_p);

+  }

+

+  /**

+   * Get or create java code annotation for given operation.

+   * @param operation_p

+   * @return

+   */

+  protected EAnnotation getOrCreateJavaCodeAnnotation(EOperation operation_p) {

+    return getOrCreateAnnotation(operation_p, JAVA_CODE_ANNOTATION_SOURCE, true);

+  }

+

+  /**

+   * Get or create pattern code annotation for given operation.<br>

+   * If creation flag is set to false, then no creation will be attempted if no annotation could be found.

+   * @param operation_p

+   * @param forceCreation_p

+   * @return

+   */

+  protected EAnnotation getOrCreatePatternCodeAnnotation(EOperation operation_p, boolean forceCreation_p) {

+    return getOrCreateAnnotation(operation_p, PATTERN_CODE_ANNOTATION_SOURCE, forceCreation_p);

+  }

+

+  /**

+   * Get annotation for given operation and source.<br>

+   * If none exists, and force creation flag is set to true, create a new one that matches these parameters.

+   * @param operation_p

+   * @param sourceAnnotation_p

+   * @param forceCreation_p Should an annotation be created if none could be found ?

+   * @return A not null annotation.

+   */

+  protected EAnnotation getOrCreateAnnotation(EOperation operation_p, String sourceAnnotation_p, boolean forceCreation_p) {

+    EAnnotation result = null;

+    // Preconditions.

+    if ((null == operation_p) && (null == sourceAnnotation_p)) {

+      return result;

+    }

+    result = operation_p.getEAnnotation(sourceAnnotation_p);

+    if ((null == result) && forceCreation_p) {

+      result = EcoreFactory.eINSTANCE.createEAnnotation();

+      result.setSource(sourceAnnotation_p);

+      operation_p.getEAnnotations().add(result);

+    }

+    return result;

+  }

+

+  /**

+   * Append operation to given string builder of pattern code.

+   * @param operationName_p Operation to use.

+   * @param parameter_p Operation parameter. Always a {@link String}. May be null.

+   * @param existingCode_p a not null {@link StringBuilder} containing existing pattern code.

+   */

+  protected void doAppendPatternCode(String operationName_p, String parameter_p, StringBuilder existingCode_p) {

+    // Preconditions.

+    if ((null == operationName_p) || (null == existingCode_p)) {

+      return;

+    }

+    // Fill up content.

+    existingCode_p.append(operationName_p);

+    // Add parameters.

+    existingCode_p.append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+    if (null != parameter_p) {

+      existingCode_p.append(parameter_p);

+    }

+    // End call.

+    existingCode_p.append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER).append(ICommonConstants.SEMICOLON_CHARACTER);

+  }

+

+  /**

+   * Annotation code appender.<br>

+   * Adds new code as an annotation to a specified operation.<br>

+   * Not dependent on the type of code to append.

+   * @author brocard

+   */

+  protected abstract class AnnotationCodeAppender {

+    /**

+     * Append new code to given operation.<br>

+     * This is done through a specific code annotation.

+     * @param operation_p

+     */

+    public void appendCode(EOperation operation_p) {

+      EAnnotation annotation = getCodeAnnotation(operation_p);

+      // Get existing code.

+      String existingContent = annotation.getDetails().get(OPERATION_ANNOTATION_BODY);

+      // Create string builder on existing code, or new one if none exists.

+      StringBuilder resultingCode = null;

+      if (null != existingContent) {

+        resultingCode = new StringBuilder(existingContent);

+      } else {

+        resultingCode = new StringBuilder();

+      }

+      // Append code to existing one.

+      doAppendCode(resultingCode);

+      // Replace code with new one.

+      annotation.getDetails().put(OPERATION_ANNOTATION_BODY, resultingCode.toString());

+    }

+

+    /**

+     * Get the annotation that is/will be containing the code.

+     * @param operation_p

+     * @return

+     */

+    protected abstract EAnnotation getCodeAnnotation(EOperation operation_p);

+

+    /**

+     * Append new code to existing one.

+     * @param existingCode_p

+     */

+    protected abstract void doAppendCode(StringBuilder existingCode_p);

+  }

+

+  /**

+   * Pattern code appender to existing pattern operation.

+   * @author brocard

+   */

+  protected abstract class PatternCodeAppender extends AnnotationCodeAppender {

+    /**

+     * @see org.eclipse.egf.pattern.ecore.AnnotationHandler.AnnotationCodeAppender#doAppendCode(java.lang.StringBuilder)

+     */

+    @Override

+    protected void doAppendCode(StringBuilder existingCode_p) {

+      doAppendPatternCode(getOperationName(), getParameter(), existingCode_p);

+    }

+

+    /**

+     * @see org.eclipse.egf.pattern.ecore.AnnotationHandler.AnnotationCodeAppender#getCodeAnnotation(org.eclipse.emf.ecore.EOperation)

+     */

+    @Override

+    protected EAnnotation getCodeAnnotation(EOperation operation_p) {

+      // Get the annotation that contains the pattern code for given operation.

+      return getOrCreatePatternCodeAnnotation(operation_p, true);

+    }

+

+    /**

+     * Get operation name to add.

+     * @return

+     */

+    protected abstract String getOperationName();

+

+    /**

+     * Get operation parameter to add.

+     * @return

+     */

+    protected abstract String getParameter();

+  }

+

+  /**

+   * Java code append to existing pattern operation code.<br>

+   * This appender always encapsulate added code within a call to string builder.<br>

+   * Thus the specified code must be compatible with an insertion within a string builder.

+   * @author brocard

+   */

+  protected abstract class JavaCodeAppender extends AnnotationCodeAppender {

+    /**

+     * @see org.eclipse.egf.pattern.ecore.AnnotationHandler.AnnotationCodeAppender#doAppendCode(java.lang.StringBuilder)

+     */

+    @Override

+    protected void doAppendCode(StringBuilder existingCode_p) {

+      existingCode_p.append(JAVA_CODE_APPEND_TO_STRING_BUILDER).append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+      appendNewOperation(existingCode_p);

+      existingCode_p.append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER).append(ICommonConstants.SEMICOLON_CHARACTER).append(ICommonConstants.EOL_CHARACTER);

+    }

+

+    /**

+     * @see org.eclipse.egf.pattern.ecore.AnnotationHandler.AnnotationCodeAppender#getCodeAnnotation(org.eclipse.emf.ecore.EOperation)

+     */

+    @Override

+    protected EAnnotation getCodeAnnotation(EOperation operation_p) {

+      return getOrCreateJavaCodeAnnotation(operation_p);

+    }

+

+    /**

+     * Append new code to existing one.<br>

+     * No specific layout is required here (even though the correctness is mandatory).

+     * @return

+     */

+    protected abstract void appendNewOperation(StringBuilder existingCode_p);

+  }

+

+  /**

+   * A java code appender that is not prefixed by a call to the string builder.<br>

+   * Used for appending string builder creation and getting string builder resulting string.

+   * @author brocard

+   */

+  protected abstract class UnbufferedJavaCodeAppender extends JavaCodeAppender {

+    /**

+     * @see org.eclipse.egf.pattern.ecore.AnnotationHandler.JavaCodeAppender#doAppendCode(java.lang.StringBuilder)

+     */

+    @Override

+    protected void doAppendCode(StringBuilder existingCode_p) {

+      appendNewOperation(existingCode_p);

+      existingCode_p.append(ICommonConstants.EOL_CHARACTER);

+    }

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/Messages.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/Messages.java
new file mode 100644
index 0000000..7ecf6f0
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/Messages.java
@@ -0,0 +1,29 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.ecore;

+

+import org.eclipse.osgi.util.NLS;

+

+/**

+ * @author Guillaume Brocard

+ *

+ */

+public class Messages extends NLS {

+  private static final String BUNDLE_NAME = "org.eclipse.egf.pattern.ecore.messages"; //$NON-NLS-1$

+  public static String PatternHandler_AutoGeneratedDescriptionText;

+  static {

+    // initialize resource bundle

+    NLS.initializeMessages(BUNDLE_NAME, Messages.class);

+  }

+  private Messages() {

+    // Static initialization.

+  }

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternConditionHelper.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternConditionHelper.java
new file mode 100644
index 0000000..f64edf4
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternConditionHelper.java
@@ -0,0 +1,44 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ **/

+package org.eclipse.egf.pattern.ecore;

+

+import java.util.List;

+

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pattern.relations.ParameterRelation;

+

+

+/**

+ * Pattern condition helper.

+ * @author Guillaume Brocard

+ */

+public class PatternConditionHelper {

+  

+  /**

+   * Get all parameters for identified pattern.<br>

+   * Does not look for parameters in current workspace.<br>

+   * <b>Should only be used by the condition producer generated result</b>!

+   * @param patternFullId_p The full id of the pattern.

+   * @return null if pattern could not be found, or empty list if it does not declare any parameter.

+   */

+  public static List<ParameterRelation> getPatternParameters(String patternFullId_p) {

+    List<ParameterRelation> result = null;

+    // Ask pattern seeker to resolve path to pattern.

+    List<PatternData> patternDataList = new PatternSeeker(false).getPatternsData(patternFullId_p);

+    if (patternDataList.isEmpty() == false) {

+      // There should be only one possible pattern data (for one pattern full id).

+      PatternData patternData = patternDataList.get(0);

+      result = patternData.getAllParameters();

+    }

+    return result;

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternConstants.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternConstants.java
new file mode 100644
index 0000000..1a7bc96
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternConstants.java
@@ -0,0 +1,122 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore;

+

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.Path;

+

+

+/**

+ * @author brocard

+ */

+public class PatternConstants {

+  

+  /**

+   * Pattern generated classes base package.

+   */

+  public static final String PATTERN_GENERATED_BASE_PACKAGE = "org.eclipse.egf.pattern"; //$NON-NLS-1$  

+  

+  /**

+   * Condition generated classes base package.

+   */

+  public static final String PATTERN_CONDITION_GENERATED_BASE_PACKAGE = "org.eclipse.egf.condition"; //$NON-NLS-1$  

+  

+  /**

+   * Pattern generated ecore namespace URI prefix

+   */

+  public static final String PATTERN_GENERATED_ECORE_NS_URI_PREFIX = "http://www.eclipse.org/egf/1.0.0/Pattern/Generated/"; //$NON-NLS-1$  

+    

+  /**

+   * Read file (pattern code tag).

+   */

+  public static final String PC_TAG_READ = "READ"; //$NON-NLS-1$

+  

+  /**

+   * Call to a super method (pattern code tag).

+   */

+  public static final String PC_TAG_SUPER = "SUPER"; //$NON-NLS-1$

+  

+  /**

+   * Call to a method (pattern code tag).

+   */

+  public static final String PC_TAG_CALL = "CALL"; //$NON-NLS-1$

+  

+  /**

+   * Call to an other pattern generate() method (pattern code tag).

+   */

+  public static final String PC_TAG_PATTERN = "PATTERN"; //$NON-NLS-1$

+    

+  /**

+   * Pattern ecore file extension.

+   */

+  public static final String PATTERN_MODEL_FILE_EXTENSION = "pm"; //$NON-NLS-1$

+  

+  /**

+   * Pattern method file extension.

+   */

+  public static final String PATTERN_METHOD_FILE_EXTENSION = "pt"; //$NON-NLS-1$  

+    

+  /**

+   * Generated source code folder (relative to project) path.

+   */

+  public static final String GENERATION_SOURCE_FOLDER = "/generated"; //$NON-NLS-1$

+  

+  /**

+   * Generated source code folder (relative to project) relative IPath.

+   */

+  public static final IPath GENERATION_SOURCE_FOLDER_IPATH = new Path("generated"); //$NON-NLS-1$  

+  

+  /**

+   * Pattern model folder.

+   */

+  public static final String PATTERN_MODEL_FOLDER = "/model/pattern/"; //$NON-NLS-1$

+  

+  /**

+   * Pattern model folder relative IPath.

+   */

+  public static final IPath PATTERN_MODEL_FOLDER_IPATH = new Path("model").append("pattern"); //$NON-NLS-1$ //$NON-NLS-2$

+  

+  /**

+   * Pattern generate method name.

+   */

+  public static final String GENERATE_METHOD_NAME = "generateBody"; //$NON-NLS-1$

+  

+  /**

+   * Generate method parameter name.

+   */

+  protected static final String GENERATE_METHOD_PARAMETER_NAME = "classLoader_p"; //$NON-NLS-1$

+  

+  /**

+   * Pattern generate pre-matching method name.

+   */

+  public static final String GENERATE_PRE_MATCHING_METHOD_NAME = "generatePreMatching"; //$NON-NLS-1$

+  

+  /**

+   * Pattern generate post-matching method name.

+   */

+  public static final String GENERATE_POST_MATCHING_METHOD_NAME = "generatePostMatching"; //$NON-NLS-1$

+  

+  /**

+   * Pattern generate header method name.

+   */

+  public static final String GENERATE_HEADER_METHOD_NAME = "generateHeader"; //$NON-NLS-1$

+  

+  /**

+   * Pattern generate footer method name.

+   */

+  public static final String GENERATE_FOOTER_METHOD_NAME = "generateFooter"; //$NON-NLS-1$

+  

+  /**

+   * Parameters handler class suffix.

+   */

+  public static final String CLASS_PARAMETERS_HANDLER_SUFFIX = "ParametersHandler"; //$NON-NLS-1$

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternHandler.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternHandler.java
new file mode 100644
index 0000000..28f0e51
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternHandler.java
@@ -0,0 +1,1033 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore;

+

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.HashSet;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Set;

+

+import org.apache.log4j.Logger;

+

+import org.eclipse.core.runtime.Path;

+import org.eclipse.jdt.core.IJavaProject;

+

+import org.eclipse.emf.common.util.EList;

+import org.eclipse.emf.common.util.EMap;

+import org.eclipse.emf.common.util.URI;

+import org.eclipse.emf.ecore.EAnnotation;

+import org.eclipse.emf.ecore.EClass;

+import org.eclipse.emf.ecore.EOperation;

+import org.eclipse.emf.ecore.EPackage;

+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.edit.command.SetCommand;

+import org.eclipse.emf.edit.domain.EditingDomain;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.constant.IPatternConstants;

+import org.eclipse.egf.common.descriptor.GenericDescriptor;

+import org.eclipse.egf.common.descriptor.IDescriptor;

+import org.eclipse.egf.common.descriptor.pattern.helper.IPatternDescriptorHandler;

+import org.eclipse.egf.common.descriptor.pattern.helper.PatternDescriptorStrategy;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.PatternHelper;

+import org.eclipse.egf.common.helper.ProjectHelper;

+import org.eclipse.egf.common.misc.PlatformLocationType;

+import org.eclipse.egf.common.ui.helper.MessageFormatHelper;

+import org.eclipse.egf.core.ui.EgfUiActivator;

+import org.eclipse.egf.fc.generator.java.helper.FileNameHelper;

+import org.eclipse.egf.model.ModelPackage;

+import org.eclipse.egf.model.PatternModel;

+import org.eclipse.egf.model.edit.helper.FactoryComponentHelper;

+import org.eclipse.egf.pattern.Pattern;

+import org.eclipse.egf.pattern.PatternPackage;

+import org.eclipse.egf.pattern.production.GeneratedContentHelper;

+import org.eclipse.egf.pattern.production.GeneratedContentProducer;

+import org.eclipse.egf.pattern.production.template.TemplateHelper;

+import org.eclipse.egf.pattern.relations.CallParameter;

+import org.eclipse.egf.pattern.relations.ParameterRelation;

+import org.eclipse.egf.pde.EgfPdeActivator;

+import org.eclipse.egf.pde.emf.plugin.command.EmfExtensionFactory;

+import org.eclipse.egf.pde.pattern.plugin.command.PatternConditionExtensionFactory;

+import org.eclipse.egf.pde.pattern.plugin.command.PatternTemplateExtensionFactory;

+import org.eclipse.egf.pde.pattern.reader.PlatformPatternExtensionReader;

+import org.eclipse.egf.pde.pattern.reader.WorkspacePatternExtensionReader;

+import org.eclipse.egf.pde.plugin.command.IPluginChangesCommand;

+import org.eclipse.egf.pde.plugin.command.IPluginChangesCommandRunner;

+import org.eclipse.egf.pde.plugin.manifest.command.ManifestChangeCommandFactory;

+

+

+/**

+ * Load a pattern from its ecore relative path.<br>

+ * Also creates a new one from its name.<br>

+ * After a pattern has been loaded or created, the instance of {@link PatternHandler} used is bound to this pattern.<br>

+ * Should another pattern be loaded/created, a new instance of {@link PatternHandler} would be used.

+ * @author Guillaume Brocard

+ */

+public class PatternHandler {

+  

+  /**

+   * Log4j reference logger.

+   */

+  private static final Logger __logger = Logger.getLogger(PatternHandler.class.getPackage().getName());

+  

+  /**

+   * Pattern loaded data.

+   */

+  private PatternData _patternData;

+  

+  /**

+   * Is pattern opened in edition mode (true) or in consultation one (false) ?

+   */

+  private boolean _editable;

+

+  /**

+   * Constructor. Pattern is in edition mode, if required.

+   */

+  public PatternHandler() {

+    this(true);

+  }

+

+  /**

+   * Constructor.

+   * @param editable_p

+   */

+  public PatternHandler(boolean editable_p) {

+    _editable = editable_p;

+  }

+

+  /**

+   * Get pattern data.

+   * @return

+   */

+  public PatternData getPatternData() {

+    return _patternData;

+  }

+

+  /**

+   * Is pattern handler enabling modifications or not ?

+   * @return

+   */

+  public boolean isEditable() {

+    return _editable;

+  }

+

+  /**

+   * Set ecore file relative path.

+   * @param fileRelativePath_p Ecore relative path, must be composed of the plug-in id (preceded by a '/') followed by the path in this plug-in.<br>

+   *          For instance <i>/org.eclipse.egf.pattern.g2/model/pattern.g2.ecore</i> is a correct entry.<br>

+   *          Setting a new value does require that {@link #load()} be called to get the content of {@link PatternData} updated.

+   * @throws IllegalArgumentException if given relative path is null.

+   */

+  public void setFileRelativePath(String fileRelativePath_p) throws Exception {

+    // Illegal argument exception.

+    if (fileRelativePath_p == null) {

+      throw new IllegalArgumentException("Null file relative path !"); //$NON-NLS-1$

+    }

+    // If pattern data does not exist yet, create it.

+    if (_patternData == null) {

+      _patternData = new PatternData();

+    }

+    // Set relative path name.

+    _patternData._fileRelativePath = fileRelativePath_p;

+  }

+

+  /**

+   * Load pattern structure using previously set ecore path.

+   * @param fileRelativePath_p Ecore relative path, must be composed of the factory component id (preceded by a '/') followed by the path in this factory component.<br>

+   *          For instance <i>/factoryComponent.121212423141443.54/model/pattern.g2.ecore</i> is a correct entry.

+   * @return A {@link PatternData} pointing to loaded pattern structure.

+   * @throws Exception

+   */

+  public PatternData load(String fileRelativePath_p) throws Exception {

+    setFileRelativePath(fileRelativePath_p);

+    // Set factory component id.

+    _patternData._fcId = new Path(_patternData._fileRelativePath).segment(0);

+    // Get containing java project.

+    _patternData._javaProject = ProjectHelper.getJavaProject(_patternData.getPluginId());

+    // Get file full URI.

+    URI fileFullUri = FileHelper.getFileFullUri(_patternData.getRealRelativePath());

+    // Unable to get it, return.

+    if (fileFullUri == null) {

+      throw new IllegalArgumentException(

+        "File relative path " //$NON-NLS-1$ 

+        + _patternData._fileRelativePath 

+        + " could not be converted to a full URI" //$NON-NLS-1$

+      );

+    }

+    // Load resource from this path.

+    ResourceSet resourceSet = new ResourceSetImpl();

+    Resource resource = resourceSet.getResource(fileFullUri, true);

+    // First element should be of EPackage type, being the pattern container.

+    EPackage containingPackage = (EPackage) resource.getContents().get(0);

+    // Look for the pattern element, should be lonely.

+    Pattern pattern = (Pattern) containingPackage.getEClassifiers().get(0);

+    _patternData._pattern = pattern;

+    _patternData._patternName = pattern.getName();

+    _patternData._patternLogicalName = pattern.getLogicalName();      

+    // Get generate body operation.

+    _patternData._generateOperation = getGenerateOperation(pattern);

+    // Get all super types.

+    List<EClass> superTypes = pattern.getESuperTypes();

+    // Try and find the super types that are patterns and get their IDs.

+    // There should be only one pattern as parent (at the most).

+    _patternData._patternDependenciesIds = new HashSet<String>(0);

+    // Set parent pattern.

+    _patternData._parentPattern = null;

+    for (EClass superType : superTypes) {

+      if (superType instanceof Pattern) {

+        _patternData._parentPattern = (Pattern) superType;

+        String patternId = (String) superType.eGet(PatternPackage.Literals.PATTERN__ID, true);

+        _patternData._patternDependenciesIds.add(patternId);

+      }

+    }

+    // Get production options handler.

+    ProductionOptionsHandler optionsHandler = _patternData.getProductionOptionsHandler();

+    // By default, always compile resulting template (that includes the 'no annotation declared' case).

+    optionsHandler._compileTemplate = true;

+    // By default, always replace standard buffer, so as to enable reporting call-back.

+    optionsHandler._bufferModification = true;

+    // Default relative path is empty.

+    optionsHandler._patternTemplatePath = ICommonConstants.EMPTY_STRING;

+    // Default enablement flag is set to false.

+    // That means no annotation locally defined.

+    optionsHandler._enabled = false;

+    // Then search for the annotation.

+    readProductionContext(pattern, _patternData);

+    // Compute all pattern matching parameters.

+    recomputeAllParameters();

+    // Get public method parameters.

+    recomputeCallParameters();

+    return _patternData;

+  }

+

+  /**

+   * Save current pattern data to pattern model file.<br>

+   * Also update given pattern model with new data.

+   * @param patternModel_p

+   * @param physicalFileRelativePath_p

+   * @return

+   * @throws Exception

+   */

+  public PatternData save(

+    PatternModel patternModel_p, 

+    String physicalFileRelativePath_p, 

+    String logicalFileRelativePath_p

+  ) throws Exception {

+    if (_patternData == null) {

+      throw new IllegalStateException("No pattern to process."); //$NON-NLS-1$

+    }

+    if (_editable == false) {

+      throw new IllegalStateException("Pattern is in read-only mode !"); //$NON-NLS-1$

+    }

+    // Get pattern to save.

+    Pattern pattern = _patternData.getPattern();

+    // Create a dedicated instance of the annotation handler.

+    AnnotationHandler annotationHandler = new AnnotationHandler();

+    // Change operations annotations.

+    AbstractPatternGenerator.computeOperationsAnnotations(pattern, _patternData.getFactoryComponentId(), annotationHandler);

+    // Proceed with production annotation.

+    handleSaveProductionOptions(pattern, annotationHandler);

+    // Write new content.

+    boolean fileSaved = AbstractPatternGenerator.writePatternModelToFile(pattern, physicalFileRelativePath_p);

+    // File could not be written.

+    if (fileSaved == false) {

+      throw new IllegalStateException("Pattern file can not be modified !"); //$NON-NLS-1$

+    }

+    // Reload pattern data content.

+    PatternData patternData = reloadPatternAndUpdateModel(patternModel_p, logicalFileRelativePath_p);

+    // Do post-save processing.

+    postSave();

+    return patternData;

+  }

+

+  /**

+   * Handle the production options saving behavior.<br>

+   * Default implementation figures out if an annotation should be saved for current pattern or not.

+   * @param pattern_p

+   * @param handler_p

+   */

+  protected void handleSaveProductionOptions(Pattern pattern_p, AnnotationHandler handler_p) {

+    ProductionOptionsHandler productionOptionsHandler = _patternData.getProductionOptionsHandler();

+    if (productionOptionsHandler.isEnabled()) {

+      AbstractPatternGenerator.computeProductionAnnotation(pattern_p, productionOptionsHandler, handler_p);

+    } else {

+      handler_p.removeProductionAnnotation(pattern_p);

+    }

+  }

+

+  /**

+   * Save current pattern data to pattern model file.<br>

+   * Also update given pattern model with new data.

+   * @param patternModel_p

+   * @return

+   * @throws Exception

+   */

+  public PatternData save(PatternModel patternModel_p) throws Exception {

+    return save(patternModel_p, _patternData.getRealRelativePath(), _patternData.getFileRelativePath());

+  }

+

+  /**

+   * Post save processing.

+   */

+  protected void postSave() {

+    // Re-compute condition structures.

+    recomputeConditionStructures();

+    // Add dependencies to external patterns.

+    ensurePluginDependencies();

+  }

+

+  /**

+   * Recompute condition structures, if needed.

+   */

+  public void recomputeConditionStructures() {

+    GeneratedContentProducer producer = new GeneratedContentProducer();

+    try {

+      producer.produceConditionStructures(_patternData);

+    } catch (Exception exception_p) {

+      StringBuilder loggerMessage = new StringBuilder("PatternHandler.recomputeConditionStructures(..) _ "); //$NON-NLS-1$

+      __logger.warn(loggerMessage.toString(), exception_p);

+    }

+  }

+

+  /**

+   * Ensure plug-in dependencies.<br>

+   * This is required at save time since the pattern might be produced.<br>

+   * This takes into account the inheritance dependency and the references ones (against called patterns).

+   */

+  protected void ensurePluginDependencies() {

+    // Resulting collection of required dependencies.

+    Collection<String> pluginIDs = new HashSet<String>(0);

+    // Create root descriptor.

+    GenericDescriptor rootDescriptor = new GenericDescriptor();

+    // Read descriptors from workspace and platform.

+    PatternDescriptorStrategy.retainRootOnly(

+      rootDescriptor, 

+      new WorkspacePatternExtensionReader().getPatternLibraries()

+    );

+    PatternDescriptorStrategy.retainRootOnly(

+      rootDescriptor, 

+      new PlatformPatternExtensionReader().getPatternLibraries()

+    );

+    final IDescriptor[] searchedDescriptor = new IDescriptor[] { null };

+    final String[] searchedFullId = new String[] { null };

+    // Search for corresponding descriptor.

+    PatternDescriptorStrategy strategy = new PatternDescriptorStrategy() {

+      @Override

+      protected boolean stopSearch(IDescriptor parentDescriptor_p) {

+        return searchedDescriptor[0] != null;

+      }

+    };

+    IPatternDescriptorHandler handler = new IPatternDescriptorHandler() {

+      public void handleDescriptor(IDescriptor descriptor_p) {

+        // Nothing to do here.

+      }

+      public void handleLibraryDescriptor(IDescriptor descriptor_p, String parentLibraryId_p) {

+        if (parentLibraryId_p.equals(searchedFullId[0])) {

+          searchedDescriptor[0] = descriptor_p;

+        }

+      }

+      public void handlePatternDescriptor(IDescriptor descriptor_p, String patternFullId_p) {

+        // Nothing to do here.

+      }

+    };

+    // Search dependencies from root library plug-in container.

+    for (String patternId : _patternData.getPatternDependenciesIds()) {

+      // Get root library id.

+      String rootLibraryId = PatternHelper.getRootLibraryId(patternId);

+      // Initialize searched full id.

+      searchedFullId[0] = rootLibraryId;

+      // Initialize resulting descriptor.

+      searchedDescriptor[0] = null;

+      // Launch search for descriptor.

+      strategy.iterateThroughPatternExtensionDescriptor(handler, rootDescriptor);

+      // Get resulting descriptor.

+      IDescriptor returnedDescriptor = searchedDescriptor[0];

+      if (returnedDescriptor != null) {

+        // Add plug-in id to known dependencies.

+        String pluginId = (String) returnedDescriptor.getValue(IPatternConstants.PATTERN_EXTENSION_CONTAINING_PLUGIN_ID);

+        // Do not add null or self dependency.

+        if (pluginId != null && pluginId.equals(_patternData.getPluginId()) == false) {

+          pluginIDs.add(pluginId);

+        }

+      }

+    }

+    // Then write result to the manifest, if it not already registered.

+    IPluginChangesCommand commandsOnManifest = ManifestChangeCommandFactory.setRequiredPlugins(

+      pluginIDs.toArray(new String[pluginIDs.size()]), 

+      false

+    );

+    EgfPdeActivator.getDefault().getPluginChangesCommandRunner().performChangesOnManifest(

+      _patternData.getPluginId(),

+      Collections.singletonList(commandsOnManifest)

+    );

+  }

+

+  /**

+   * Reload pattern data and update pattern model accordingly.

+   * @param patternModel_p

+   * @param fileRelativePath_p

+   * @return

+   * @throws Exception if pattern data could not be reloaded.

+   */

+  protected PatternData reloadPatternAndUpdateModel(PatternModel patternModel_p, String fileRelativePath_p) throws Exception {

+    PatternData result = load(fileRelativePath_p);

+    if (_editable) {

+      updatePatternModel(patternModel_p, result);

+    }

+    return result;

+  }

+

+  /**

+   * Update pattern model with new pattern name, path and id.

+   * @param patternModel_p

+   */

+  protected void updatePatternModel(PatternModel patternModel_p, PatternData patternData_p) {

+    // Preconditions.

+    if (patternData_p == null || patternModel_p == null) {

+      return;

+    }

+    // Set pattern path.

+    patternModel_p.setPath(patternData_p.getFileRelativePath());

+    // Update pattern model through editing domain so as to force modification of the plugin.xml file.

+    EditingDomain editingDomain = EgfUiActivator.getDefault().getEditingDomain();

+    editingDomain.getCommandStack().execute(

+      SetCommand.create(

+        editingDomain, 

+        patternModel_p, 

+        ModelPackage.Literals.NAMED_MODEL_ELEMENT_WITH_ID__NAME,

+        patternData_p.getPatternLogicalName()

+      )

+    );

+  }

+

+  /**

+   * Create a new pattern out of given pattern model.

+   * @param fcId_p

+   * @param patternModel_p

+   * @return A {@link PatternData} pointing to created pattern structure.

+   * @throws Exception.

+   */

+  public PatternData createPattern(final String fcId_p, final PatternModel patternModel_p) throws Exception {

+    // Preconditions.

+    if (patternModel_p == null || fcId_p == null || _editable == false) {

+      return null;

+    }

+    // If handled pattern data does not exist yet, create it.

+    if (_patternData == null) {

+      _patternData = new PatternData();

+    }

+    // New pattern name.

+    final String name = patternModel_p.getName();    // And id.

+    final String[] id = new String[] { null };

+    // Write model.

+    new AbstractPatternGenerator() {

+      @Override

+      protected void fillPattern(Pattern newPattern_p, AnnotationHandler handler_p, EOperation generate_p) {

+        newPattern_p.setName(GeneratedContentHelper.getPatternClassName(newPattern_p));

+        newPattern_p.setLogicalName(name);        

+        newPattern_p.setDescription(

+          MessageFormatHelper.formatMessage(

+            Messages.PatternHandler_AutoGeneratedDescriptionText, 

+            new Object[] { name }

+          )

+        );

+      }

+      @Override

+      public String getPatternContainingPluginId() {

+        return FactoryComponentHelper.getPluginId(fcId_p, PlatformLocationType.WORKSPACE_ONLY);

+      }

+      @Override

+      public String getPatternFullId() {

+        id[0] = patternModel_p.getId();

+        // Given pattern model id must be the containing library full id.

+        return id[0];

+      }

+    }.generateEcoreFile();

+    // Get relative path.

+    String fileRelativePath = AbstractPatternGenerator.getPatternModelRelativePath(

+      fcId_p, 

+      PatternHelper.deresolveId(id[0]).getValue()

+    );

+    // Then reload it.

+    return reloadPatternAndUpdateModel(patternModel_p, fileRelativePath);

+  }

+

+  /**

+   * Delete the handled pattern.<br>

+   * User is advised to release held pattern data reference, since it is no longer synchronized with the persisted data.

+   */

+  public void delete() {

+    // First of all clean generated structures.

+    cleanGeneratedStructures();

+    // Then clean user templates.

+    String pluginId = _patternData.getPluginId();

+    FileHelper.deleteFolder(TemplateHelper.getPatternTemplatesFolderRelativePaths(_patternData.getPattern().getShortId(), pluginId).getKey());

+    // Update plugin.xml content accordingly.

+    IPluginChangesCommandRunner runner = EgfPdeActivator.getDefault().getPluginChangesCommandRunner();

+    runner.performChangesOnPlugin(

+      pluginId, 

+      Collections.singletonList(

+        PatternConditionExtensionFactory.unsetPatternConditionExtension(_patternData.getPattern().getId())

+      )

+    );

+    // Delete condition class.

+    String conditionClassRelativePath = GeneratedContentProducer.getConditionFileRelativePath(_patternData);

+    FileHelper.deleteFile(conditionClassRelativePath);

+    // Finally, delete pattern model.

+    FileHelper.deleteFile(_patternData.getRealRelativePath());

+    // Unload pattern data.

+    _patternData = null;

+  }

+

+  /**

+   * Clean pattern generated structures.<br>

+   * List of deleted items :<br>

+   * <ul>

+   * <li>EMF generated classes (based on the pattern model)</li>

+   * <li>Exported runtime section for these classes</li>

+   * <li>Generated package extension for these classes</li>

+   * <li>Generated templates : pre/post matchings and computed whole template file</li>

+   * <li>Generated template class, if any</li>

+   * <li>Generated pattern extension, if any</li>

+   * </ul>

+   */

+  public void cleanGeneratedStructures() {

+    // Plug-in id.

+    String pluginId = _patternData.getPluginId();

+    // Pattern full id.

+    // Pattern name.

+    String patternName = _patternData.getPatternName();

+    // Command runner.

+    IPluginChangesCommandRunner pluginChangesCommandRunner = EgfPdeActivator.getDefault().getPluginChangesCommandRunner();

+    // First of all, clean generated classes.

+    // Clean generation model.

+    String genModelRelativePath = FileNameHelper.getGenModelPath(new Path(_patternData.getRealRelativePath()));

+    FileHelper.deleteFile(genModelRelativePath);

+    // Clean EMF classes.

+    String rootPackageRelativePath = GeneratedContentHelper.getEMFGeneratedRootFolderRelativePath(_patternData);

+    FileHelper.deleteFolder(rootPackageRelativePath);

+    // Clean the exported runtime section if necessary

+    List<String> packageNames = GeneratedContentHelper.getEMFGeneratedPackagesNames(_patternData);

+    List<IPluginChangesCommand> suppressRuntimePackagesCommand = Collections.singletonList(

+      ManifestChangeCommandFactory.unsetExportedPackages(

+        packageNames.toArray(

+          new String[packageNames.size()]

+        )

+      )

+    );

+    pluginChangesCommandRunner.performChangesOnManifest(

+      pluginId, 

+      suppressRuntimePackagesCommand

+    );

+    // Suppress generated package extension.

+    List<IPluginChangesCommand> suppressGeneratedPackageCommand = Collections.singletonList(

+      EmfExtensionFactory.unsetEmfGeneratedPackageExtension(GeneratedContentHelper.getPatternPackageNsURI(_patternData.getPattern()))

+    );

+    pluginChangesCommandRunner.performChangesOnPlugin(pluginId, suppressGeneratedPackageCommand);

+    // Clean generated templates.

+    // Starts with generated template file.

+    String generatedTemplateFilePath = TemplateHelper.getPatternTemplatePath(_patternData);

+    FileHelper.deleteFile(generatedTemplateFilePath);

+    // Then suppress generated templates.

+    FileHelper.deleteFolder(TemplateHelper.getPatternTemplatesFolderRelativePaths(_patternData.getPattern().getShortId(), pluginId).getValue());

+    // Clean template resulting class.

+    String generatedPatternClassRelativePath = GeneratedContentHelper.getGeneratedPatternClassRelativePath(_patternData);

+    if (generatedPatternClassRelativePath != null) {

+      FileHelper.deleteFile(generatedPatternClassRelativePath);

+    }

+    // Suppress generated pattern extension.

+    pluginChangesCommandRunner.performChangesOnPlugin(

+      pluginId, 

+      Collections.singletonList(PatternTemplateExtensionFactory.unsetPatternTemplateExtension(_patternData.getPattern().getShortId()))

+    );

+    // Remove parameters handler class.

+    String generatedParametersHandlerClassRelativePath = GeneratedContentProducer.getGeneratedClassRelativePath(

+      pluginId, 

+      PatternConstants.GENERATION_SOURCE_FOLDER, 

+      PatternConstants.PATTERN_GENERATED_BASE_PACKAGE,

+      GeneratedContentProducer.getClassName(

+        patternName,

+        PatternConstants.CLASS_PARAMETERS_HANDLER_SUFFIX

+      )

+    );

+    FileHelper.deleteFile(generatedParametersHandlerClassRelativePath);

+    // Remove exported package.

+    pluginChangesCommandRunner.performChangesOnManifest(

+      pluginId, 

+      Collections.singletonList(

+        ManifestChangeCommandFactory.unsetExportedPackages(

+          new String[] { 

+            PatternConstants.PATTERN_GENERATED_BASE_PACKAGE 

+          }

+        )

+      )

+    );

+  }

+

+  /**

+   * Read production context, looking for both given pattern and its parents (patterns).

+   * @param pattern_p

+   * @param patternData_p

+   * @return

+   */

+  protected boolean readProductionContext(Pattern pattern_p, PatternData patternData_p) {

+    boolean result = false;

+    // Precondition.

+    if (pattern_p == null) {

+      return result;

+    }

+    // Search for given pattern.

+    EAnnotation productionAnnotation = pattern_p.getEAnnotation(AnnotationHandler.PATTERN_PRODUCTION_ANNOTATION_SOURCE);

+    result = productionAnnotation != null;

+    if (result) {

+      // Get production options handler.

+      ProductionOptionsHandler optionsHandler = patternData_p.getProductionOptionsHandler();

+      // Set activation flag.

+      optionsHandler._enabled = (pattern_p == patternData_p.getPattern());

+      // Get annotation details.

+      EMap<String, String> details = productionAnnotation.getDetails();

+      // Compilation flag.

+      String compileString = details.get(AnnotationHandler.PATTERN_PRODUCTION_ANNOTATION_BODY_COMPILATION);

+      // Tested against null because null would return a false boolean, where true should be used.

+      if (compileString != null) {

+        optionsHandler._compileTemplate = Boolean.valueOf(compileString).booleanValue();

+      }

+      // Buffer modification flag.

+      String modifyBuffer = details.get(AnnotationHandler.PATTERN_PRODUCTION_ANNOTATION_BODY_BUFFER_MODIFICATION);

+      if (modifyBuffer != null) {

+        optionsHandler._bufferModification = Boolean.valueOf(modifyBuffer).booleanValue();

+      }

+      // Template path.

+      String path = details.get(AnnotationHandler.PATTERN_PRODUCTION_ANNOTATION_BODY_PATH);

+      if (path != null) {

+        optionsHandler._patternTemplatePath = path;

+      }

+    } else {

+      // Get parent types.

+      List<EClass> parentTypes = pattern_p.getESuperTypes();

+      if (parentTypes.isEmpty() == false) {

+        // Try and find pattern parents.

+        for (Iterator<EClass> parents = parentTypes.iterator(); parents.hasNext() && result == false;) {

+          EClass parent = parents.next();

+          if (parent instanceof Pattern) {

+            result = readProductionContext((Pattern) parent, patternData_p);

+          }

+        }

+      }

+    }

+    return result;

+  }

+

+  /**

+   * Get all pattern matching parameters for given pattern.<br>

+   * Includes all first-level and inherited parameters.<br>

+   * Parent parameters are presented first, from the farthest to the nearest.<br>

+   * Thus given pattern parameters appear at the end of resulting list.

+   * @param pattern_p

+   * @return A not null list of {@link ParameterRelation}. Can still be empty.

+   */

+  protected List<ParameterRelation> getAllParameters(Pattern pattern_p) {

+    List<ParameterRelation> result = null;

+    // Precondition.

+    if (pattern_p == null) {

+      result = Collections.emptyList();

+    }

+    // Initiate search.

+    result = new ArrayList<ParameterRelation>(pattern_p.getParameters().size());

+    // Get parent types.

+    List<EClass> parentTypes = pattern_p.getESuperTypes();

+    if (parentTypes.isEmpty() == false) {

+      // Try and find pattern parents.

+      for (EClass parent : parentTypes) {

+        if (parent instanceof Pattern) {

+          // Add their parameters first.

+          List<ParameterRelation> parentResult = getAllParameters((Pattern) parent);

+          result.addAll(parentResult);

+        }

+      }

+    }

+    // Add first-level parameters too.

+    result.addAll(pattern_p.getParameters());

+    return result;

+  }

+

+  /**

+   * Get all public method parameters for given pattern.<br>

+   * Includes at least all first-level parameters.

+   * @param pattern_p

+   * @return A not null list of {@link CallParameter}. Can nevertheless be empty.

+   */

+  protected List<CallParameter> getCallParameters(Pattern pattern_p) {

+    List<CallParameter> result = null;

+    // Precondition.

+    if (pattern_p == null) {

+      result = Collections.emptyList();

+    }

+    // Initiate search.

+    EList<CallParameter> callParameters = pattern_p.getCallParameters();

+    result = new ArrayList<CallParameter>(callParameters.size());

+    // For now, simply add current level parameters.

+    result.addAll(callParameters);

+    return result;

+  }

+

+  /**

+   * Recompute all pattern matching parameters.<br>

+   * As a result, contained pattern data is modified.

+   * @return

+   */

+  public List<ParameterRelation> recomputeAllParameters() {

+    _patternData._parameters = getAllParameters(_patternData.getPattern());

+    return _patternData._parameters;

+  }

+

+  /**

+   * Recompute all public method parameters.<br>

+   * As a result, contained pattern data is modified.

+   * @return

+   */

+  public List<CallParameter> recomputeCallParameters() {

+    _patternData._callParameters = getCallParameters(_patternData.getPattern());

+    return _patternData._callParameters;

+  }

+

+  /**

+   * Get user modifiable generate operation.

+   * @param pattern_p

+   * @return

+   */

+  protected EOperation getGenerateOperation(Pattern pattern_p) {

+    EOperation result = null;

+    // Precondition.

+    if (pattern_p == null) {

+      return result;

+    }

+    List<EOperation> operationsList = pattern_p.getEOperations();

+    for (Iterator<EOperation> operations = operationsList.iterator(); operations.hasNext() && result == null;) {

+      EOperation currentOperation = operations.next();

+      if (PatternConstants.GENERATE_METHOD_NAME.equals(currentOperation.getName())) {

+        result = currentOperation;

+      }

+    }

+    return result;

+  }

+

+  /**

+   * Pattern data.<br>

+   * Provides with different pieces of information for locating the pattern file and details about its content.

+   */

+  public class PatternData {

+    

+    /**

+     * Ecore file relative path. It is composed of the factory component id containing the pattern, plus the path inside the factory component to the ecore file.

+     */

+    protected String _fileRelativePath;

+    

+    /**

+     * The containing factory component id.

+     */

+    protected String _fcId;

+    

+    /**

+     * Java project containing the pattern.<br>

+     * Null means pattern has already been deployed.

+     */

+    protected IJavaProject _javaProject;

+    

+    /**

+     * Pattern reference as object loaded from the ecore file.<br>

+     * Does not stand for the generated one.

+     */

+    protected Pattern _pattern;

+    

+    /**

+     * Pattern name.

+     */

+    protected String _patternName;

+    

+    /**

+     * Pattern logical name.

+     */

+    protected String _patternLogicalName;    

+        

+    /**

+     * Set of parent patterns full ids.

+     */

+    protected Set<String> _patternDependenciesIds;

+    

+    /**

+     * All pattern matching parameters, including parents ones.

+     */

+    protected List<ParameterRelation> _parameters;

+    

+    /**

+     * Public method parameters.

+     */

+    protected List<CallParameter> _callParameters;

+    

+    /**

+     * Generate operation.

+     */

+    protected EOperation _generateOperation;

+    

+    /**

+     * Parent pattern, if any.

+     */

+    protected Pattern _parentPattern;

+    

+    /**

+     * Production options handler.

+     */

+    protected ProductionOptionsHandler _productionOptionsHandler;    

+

+    /**

+     * Get generate operation.

+     * @return

+     */

+    public EOperation getGenerateOperation() {

+      return _generateOperation;

+    }

+

+    /**

+     * Get real pattern model file relative path, based on factory component id to plug-in id resolution mechanism.

+     * @return

+     */

+    public String getRealRelativePath() {

+      return TemplateHelper.getPhysicalRelativePath(_fileRelativePath, getPluginId());

+    }

+

+    /**

+     * @return the fileRelativePath

+     */

+    public String getFileRelativePath() {

+      return _fileRelativePath;

+    }

+

+    /**

+     * @return the pluginId

+     */

+    public String getPluginId() {

+      // Resolve plug-in id from factory component one.

+      String result = FactoryComponentHelper.getPluginId(

+        _fcId, 

+        PlatformLocationType.WORKSPACE_THEN_TARGET_PLATFORM

+      );

+      // Could not find plug-in from factory component one.

+      // Return factory component id, hoping that it is in fact a plug-in id that has not been migrated.

+      if (result == null) {

+        result = _fcId;

+      }

+      return result;

+    }

+

+    /**

+     * Get factory component id.

+     * @return

+     */

+    public String getFactoryComponentId() {

+      return _fcId;

+    }

+

+    /**

+     * @return the javaProject

+     */

+    public IJavaProject getJavaProject() {

+      return _javaProject;

+    }

+

+    /**

+     * @return the pattern

+     */

+    public Pattern getPattern() {

+      return _pattern;

+    }

+

+    /**

+     * @return the patternName

+     */

+    public String getPatternName() {

+      return _patternName;

+    }

+    

+    /**

+     * @return the patternLogicalName

+     */

+    public String getPatternLogicalName() {

+      return _patternLogicalName;

+    }

+    

+    /**

+     * @set the patternLogicalName

+     */

+    public void setPatternLogicalName(String patternLogicalName_p) {

+      _patternLogicalName = patternLogicalName_p;

+    }      

+

+    /**

+     * @return the patternDependenciesIds

+     */

+    public Set<String> getPatternDependenciesIds() {

+      return _patternDependenciesIds;

+    }

+

+    /**

+     * Get production options handler.

+     * @return

+     */

+    public ProductionOptionsHandler getProductionOptionsHandler() {

+      if (_productionOptionsHandler == null) {

+        _productionOptionsHandler = new ProductionOptionsHandler();

+      }

+      return _productionOptionsHandler;

+    }

+

+    /**

+     * Get all pattern matching parameters, including parents ones, starting from farthest (higher parent) to closest (current pattern) parameters.

+     * @return the parameters

+     */

+    public List<ParameterRelation> getAllParameters() {

+      return _parameters;

+    }

+

+    /**

+     * Get all public method parameters, also stated as 'Call parameters'.<br>

+     * @return

+     */

+    public List<CallParameter> getCallParameters() {

+      return _callParameters;

+    }

+

+    /**

+     * Get parent pattern.

+     * @return the parentPattern

+     */

+    public Pattern getParentPattern() {

+      return _parentPattern;

+    }

+

+    /**

+     * Clean generated structures.<br>

+     * This is a convenient method for fixing inheritance error bug in 1.2.0_M4.<br>

+     * There should not be such method in {@link PatternData}.<br>

+     * TODO Guillaume. Remove this method from 1.2.0_M5 release and replace it with an access to pattern handlers in pattern producer.

+     */

+    public void cleanGeneratedStructures() {

+      PatternHandler.this.cleanGeneratedStructures();

+    }

+    

+  }

+

+  /**

+   * Production options handler.

+   */

+  public class ProductionOptionsHandler {

+    

+    /**

+     * Pattern template path, if default behavior is to be overridden.

+     */

+    protected String _patternTemplatePath;

+    

+    /**

+     * Should resulting template file be compiled ?

+     */

+    protected boolean _compileTemplate;

+    

+    /**

+     * Should buffers be modified, as opposed to using the default declaration.

+     */

+    protected boolean _bufferModification;

+    

+    /**

+     * Are options enabled (true) or not (false) ?<br>

+     * If false, the pattern annotation will be destroyed at next save time.

+     */

+    protected boolean _enabled;

+

+    /**

+     * @return the patternTemplatePath

+     */

+    public String getPatternTemplatePath() {

+      return _patternTemplatePath;

+    }

+

+    /**

+     * Set pattern template production relative path.<br>

+     * If set to a not null, non-empty value, then default pattern production behavior is overridden.<br>

+     * The template is no longer produced in <b>templates/generated</b> folder, but in <b>templates/<code>patternTemplatePath_p</code></b> instead. Set again to

+     * null or {@link ICommonConstants#EMPTY_STRING} if default behavior must be restored.

+     * @param patternTemplatePath_p

+     */

+    public void setPatternTemplatePath(String patternTemplatePath_p) {

+      _patternTemplatePath = patternTemplatePath_p;

+    }

+

+    /**

+     * @return the compileTemplate

+     */

+    public boolean shouldCompileTemplate() {

+      return _compileTemplate;

+    }

+

+    /**

+     * Set compile template flag to given one.<br>

+     * If set to true (the default value), then the pattern template is compiled into a Java class.<br>

+     * If set to false, the pattern template file is assembled, but not compiled into a Java class.

+     * @param compile_p

+     */

+    public void setCompileTemplateTo(boolean compile_p) {

+      _compileTemplate = compile_p;

+    }

+

+    /**

+     * Should template buffer be modified (true), including replacement, or should standard way be used (false) ?

+     * @return

+     */

+    public boolean shouldModifyBuffer() {

+      return _bufferModification;

+    }

+

+    /**

+     * Set modify buffer flag to given one.<br>

+     * The buffer modification is required for pattern reporting at runtime.<br>

+     * If set to true (the default value), then the reporting of generation at runtime is active.<br>

+     * If set to false, the default JET behavior is left untouched. That is compatible with EMF-like patterns, but no longer with Pattern Runner execution.

+     * Indeed, EMF-like patterns are expecting JET to behave standardly (and have no use of Pattern Runner as the execution environment).

+     * @param modifyBuffer_p

+     */

+    public void setModifyBufferTo(boolean modifyBuffer_p) {

+      _bufferModification = modifyBuffer_p;

+    }

+

+    /**

+     * Are options locally enabled ?

+     * @return

+     */

+    public boolean isEnabled() {

+      return _enabled;

+    }

+

+    /**

+     * Set options enablement to given value.

+     * @param enabled_p

+     */

+    public void setEnabled(boolean enabled_p) {

+      _enabled = enabled_p;

+    }

+    

+  }

+  

+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternSeeker.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternSeeker.java
new file mode 100644
index 0000000..4ff26b6
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/PatternSeeker.java
@@ -0,0 +1,278 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore;

+

+import java.util.ArrayList;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+

+import org.apache.log4j.Logger;

+import org.eclipse.egf.common.constant.IPatternConstants;

+import org.eclipse.egf.common.descriptor.IDescriptor;

+import org.eclipse.egf.common.helper.ExtensionPointHelper;

+import org.eclipse.egf.common.helper.PatternLibrarySequenceHelper;

+import org.eclipse.egf.common.helper.StringHelper;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pde.pattern.reader.IPatternExtensionReader;

+import org.eclipse.egf.pde.pattern.reader.PlatformPatternExtensionReader;

+import org.eclipse.egf.pde.pattern.reader.WorkspacePatternExtensionReader;

+

+

+/**

+ * A pattern seeker that takes a full id as parameter and is able to retrieve all corresponding patterns.<br>

+ * The full id can either be the id of a library or the id of a single pattern.

+ * @author Guillaume Brocard

+ */

+public class PatternSeeker {

+  

+  /**

+   * Log4j reference logger.

+   */

+  private static final Logger __logger = Logger.getLogger(PatternSeeker.class.getPackage().getName());

+  

+  /**

+   * Pattern extension readers.

+   */

+  private List<IPatternExtensionReader> _readers;

+

+  /**

+   * Constructor.

+   * @param searchInWorkspace_p Should extensions be read in workspace too ?

+   */

+  public PatternSeeker(boolean searchInWorkspace_p) {

+    _readers = new ArrayList<IPatternExtensionReader>(1);

+    if (searchInWorkspace_p) {

+      _readers.add(new WorkspacePatternExtensionReader());

+    }

+    _readers.add(new PlatformPatternExtensionReader());

+  }

+

+  /**

+   * Get patterns from full id.<br>

+   * @param fullId_p The full id is composed of the chain of containing libraries and optionally the pattern id, separated by the <i>#</i> character.<br>

+   *          E.g :

+   *          <ul>

+   *          <li> <i>HelloWorld.Library1#Library2#Pattern1</i><br>

+   *          In this case, only Pattern1 will be produced.

+   *          <li> <i>HelloWorld.Library1#Library2</i><br>

+   *          In this one, the whole library Library2 will be produced, according to its orchestration class.

+   *          </ul>

+   * @return not null, may be empty if no pattern to produce could be found.

+   */

+  public List<PatternData> getPatternsData(String fullId_p) {

+    // Create resulting list.

+    List<PatternData> result = new ArrayList<PatternData>(0);

+    // Search for corresponding patterns.

+    getPatternsData(fullId_p, fullId_p, null, result);

+    return result;

+  }

+

+  /**

+   * Get root library from its id.

+   * @param libraryId_p

+   * @return

+   */

+  protected IDescriptor getRootLibraryFromId(String libraryId_p) {

+    IDescriptor result = null;

+    // Iterate over declared possible readers.

+    for (Iterator<IPatternExtensionReader> readers = _readers.iterator(); readers.hasNext() && result == null;) {

+      result = readers.next().getPatternLibrary(libraryId_p);

+    }

+    return result;

+  }

+

+  /**

+   * Get children libraries of given one.

+   * @param parentLibrary_p

+   * @return

+   */

+  protected List<IDescriptor> getChildrenLibraries(IDescriptor parentLibrary_p) {

+    // All children.

+    List<IDescriptor> children = parentLibrary_p.getChildren();

+    List<IDescriptor> result = new ArrayList<IDescriptor>(children.size());

+    // Keep only those that have the 'library' type set.

+    for (IDescriptor descriptor : children) {

+      if (IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_LIBRARY.equals(descriptor.getValue(IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_TYPE))) {

+        result.add(descriptor);

+      }

+    }

+    return result;

+  }

+

+  /**

+   * Get patterns data from given full id.

+   * @param fullId_p The original full id.

+   * @param partialId_p The partial id, as required by the search step.

+   * @param library_p The extension point element representing a library at given search step.

+   * @param data_p Resulting list of patterns data (to produce).

+   */

+  protected void getPatternsData(String fullId_p, String partialId_p, IDescriptor library_p, List<PatternData> data_p) {

+    // Precondition.

+    if (partialId_p == null) {

+      return;

+    }

+    // Search libraries/patterns separator in pattern id.

+    int separatorPosition = partialId_p.indexOf(IPatternConstants.LIBRARY_PATTERN_ID_SEPARATOR);

+    // Check that path is composed of one library at least.

+    if (separatorPosition > 0) {

+      // There is still work to do before reaching the end-of-chain library.

+      String libraryId = partialId_p.substring(0, separatorPosition);

+      IDescriptor library = null;

+      if (library_p == null) {

+        // No parent library, look for first one.

+        library = getRootLibraryFromId(libraryId);

+      } else {

+        // Look for children libraries.

+        List<IDescriptor> libraries = getChildrenLibraries(library_p);

+        for (Iterator<IDescriptor> librariesIterator = libraries.iterator(); librariesIterator.hasNext() && library == null;) {

+          IDescriptor currentLibrary = librariesIterator.next();

+          // Got the one !

+          if (libraryId.equals(currentLibrary.getValue(ExtensionPointHelper.ATT_ID))) {

+            library = currentLibrary;

+          }

+        }

+      }

+      // Go on with this selected level of library.

+      if (library != null) {

+        getPatternsData(

+          fullId_p, 

+          partialId_p.substring(separatorPosition + 1, partialId_p.length()), 

+          library, 

+          data_p

+        );

+      }

+    } else if (library_p != null) {

+      // At this point, the parent library is reached.

+      // It contains either the library or the pattern to produce.

+      doGetPatternPaths(partialId_p, library_p, data_p);

+    } else {

+      // No parent library, asking for root library production

+      // (indeed a pattern is contained in one and only one library).

+      IDescriptor library = getRootLibraryFromId(fullId_p);

+      resolveLibraryData(library, data_p);

+    }

+  }

+

+  /**

+   * Do retrieved all patterns data from reached library.

+   * @param partialId_p Either a library or pattern id.

+   * @param library_p Reached parent library.

+   * @param data_p Resulting patterns data list.

+   */

+  protected void doGetPatternPaths(String partialId_p, IDescriptor library_p, List<PatternData> data_p) {

+    // Look for a child element that is identified by the given partial id.

+    List<IDescriptor> children = library_p.getChildren();

+    // Search among existing children.

+    for (Iterator<IDescriptor> descriptors = children.iterator(); descriptors.hasNext();) {

+      IDescriptor currentElement = descriptors.next();

+      if (partialId_p.equals(currentElement.getValue(ExtensionPointHelper.ATT_ID))) {

+        String descriptorType = (String) currentElement.getValue(IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_TYPE);

+        if (IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_LIBRARY.equals(descriptorType)) {

+          // Found library to produce, add its patterns data.

+          resolveLibraryData(currentElement, data_p);

+        } else {

+          // Found pattern to produce, add its path.

+          PatternData patternData = resolvePatternData(currentElement);

+          if (patternData != null) {

+            data_p.add(patternData);

+          }

+        }

+        break;

+      }

+    }

+  }

+

+  /**

+   * Resolve library patterns data that should be produced.

+   * @param library_p

+   * @param data_p

+   */

+  protected void resolveLibraryData(IDescriptor library_p, List<PatternData> data_p) {

+    // The containing library is reached, look for its patterns.

+    // First of all, try and use the orchestration string as a list of patterns/libraries to produce.

+    String orchestrationString = (String) library_p.getValue(IPatternConstants.LIBRARY_PRODUCTION_ORCHESTRATION_ATTRIBUTE_NAME);

+    String[] ids = null;

+    if (orchestrationString != null) {

+      ids = StringHelper.getTokens(orchestrationString, PatternLibrarySequenceHelper.SEQUENCE_SEPARATORS);

+    }

+    // Get library elements.

+    List<IDescriptor> elements = library_p.getChildren();

+    // Cycle through the ids.

+    Map<String, IDescriptor> elementsFromId = null;

+    if (ids != null) {

+      // First, create the map of (id, configuration element) that will be used while searching by ids.

+      elementsFromId = new HashMap<String, IDescriptor>(elements.size());

+      for (IDescriptor element : elements) {

+        elementsFromId.put((String) element.getValue(ExtensionPointHelper.ATT_ID), element);

+      }

+      // Then do return pattern paths, according to orchestration ids.

+      for (String currentId : ids) {

+        // Get element from id, according to the orchestration schema.

+        IDescriptor currentElement = elementsFromId.get(currentId);

+        // Do resolve paths.

+        doResolveLibraryData(currentElement, data_p);

+      }

+    } else { // No orchestration defined, simply cycle through existing child elements in declaration order.

+      for (IDescriptor element : elements) {

+        // Do resolve paths.

+        doResolveLibraryData(element, data_p);

+      }

+    }

+  }

+

+  /**

+   * Do resolve given library child data.

+   * @param libraryChild_p

+   * @param data_p

+   */

+  protected void doResolveLibraryData(IDescriptor libraryChild_p, List<PatternData> data_p) {

+    if (libraryChild_p == null || data_p == null) {

+      return;

+    }

+    // The child element is a library itself, resolve as a library then.

+    String childType = (String) libraryChild_p.getValue(IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_TYPE);

+    if (IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_LIBRARY.equals(childType)) {

+      resolveLibraryData(libraryChild_p, data_p);

+    } else { // The child element is a pattern, add its data to the resulting list.

+      PatternData patternData = resolvePatternData(libraryChild_p);

+      if (patternData != null) {

+        data_p.add(patternData);

+      }

+    }

+  }

+

+  /**

+   * Resolve pattern data from its descriptor.

+   * @param pattern_p

+   * @return

+   */

+  protected PatternData resolvePatternData(IDescriptor pattern_p) {

+    // Create corresponding pattern structure.

+    PatternData result = null;

+    // Get file path.

+    String fileDeclaredPath = (String) pattern_p.getValue(IPatternConstants.PATTERN_MODEL_ATTRIBUTE_NAME);

+    // Could not retrieve ecore relative path, return null.

+    if (fileDeclaredPath == null) {

+      return result;

+    }

+    // Try and load pattern model.

+    try {

+      result = new PatternHandler().load(fileDeclaredPath);

+    } catch (Exception exception_p) {

+      StringBuilder loggerMessage = new StringBuilder("PatternProducer.resolvePatternData(..) _ "); //$NON-NLS-1$

+      __logger.warn(loggerMessage.toString(), exception_p);

+    }

+    return result;

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/AbstractPatternCondition.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/AbstractPatternCondition.java
new file mode 100644
index 0000000..a635cca
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/AbstractPatternCondition.java
@@ -0,0 +1,41 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore.condition;

+

+import org.eclipse.egf.core.context.ProductionContext;

+

+/**

+ * A default root implementation that provides a context to the condition class real implementation.

+ * @author Guillaume Brocard

+ */

+public abstract class AbstractPatternCondition implements IPatternCondition {

+  

+  /**

+   * The production context reference.

+   */

+  private ProductionContext _context;

+

+  /**

+   * @see org.eclipse.egf.pattern.ecore.condition.IPatternCondition#setContext(org.eclipse.egf.core.context.ProductionContext)

+   */

+  public void setContext(ProductionContext context_p) {

+    _context = context_p;

+  }

+

+  /**

+   * Get available production context.

+   * @return <code>null</code> if none is available.

+   */

+  protected ProductionContext getContext() {

+    return _context;

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/ConditionClassOutput.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/ConditionClassOutput.java
new file mode 100644
index 0000000..ac98fb6
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/ConditionClassOutput.java
@@ -0,0 +1,82 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore.condition;

+

+/**

+ * Container for the generated output.

+ * @author Guillaume Brocard

+ */

+public class ConditionClassOutput {

+  

+  /**

+   * Shared instance.

+   */

+  private static ConditionClassOutput __shared;

+  

+  /**

+   * Generated condition class content.

+   */

+  private String _generatedConditionClassContent;

+  

+  /**

+   * Pattern that should own the result.

+   */

+  private String _patternFullId;

+

+  /**

+   * Constructor.

+   */

+  private ConditionClassOutput() {

+    __shared = this;

+  }

+

+  /**

+   * Get shared instance at the time of calling.

+   * @return

+   */

+  public static ConditionClassOutput getSharedInstance() {

+    if (null == __shared) {

+      __shared = new ConditionClassOutput();

+    }

+    return __shared;

+  }

+

+  /**

+   * Reset stored values.

+   */

+  public void reset() {

+    _generatedConditionClassContent = null;

+    _patternFullId = null;

+  }

+

+  /**

+   * Get generated condition class content.

+   * @param patternFullId_p Identified owner of the result.

+   * @return null if there is no result for identified pattern.

+   */

+  public String getGeneratedConditionClassContent(String patternFullId_p) {

+    if (patternFullId_p == null || patternFullId_p.equals(_patternFullId) == false) {

+      return null;

+    }

+    return _generatedConditionClassContent;

+  }

+

+  /**

+   * Set generated condition class content for identified pattern.

+   * @param generatedConditionClassContent_p

+   * @param patternFullId_p

+   */

+  public void setGeneratedConditionClassContent(String generatedConditionClassContent_p, String patternFullId_p) {

+    _patternFullId = patternFullId_p;

+    _generatedConditionClassContent = generatedConditionClassContent_p;

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/GeneratedConditionProducer.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/GeneratedConditionProducer.java
new file mode 100644
index 0000000..9071a84
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/GeneratedConditionProducer.java
@@ -0,0 +1,210 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore.condition;

+

+import java.util.Iterator;

+import java.util.List;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.helper.EcoreHelper;

+import org.eclipse.egf.pattern.ecore.PatternConstants;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pattern.production.GeneratedContentProducer;

+import org.eclipse.egf.pattern.relations.ParameterRelation;

+import org.eclipse.emf.ecore.EPackage;

+

+

+/**

+ * @author Guillaume Brocard

+ */

+public class GeneratedConditionProducer {

+  

+  /**

+   * Check real implementation default code.

+   */

+  protected static final String CHECK_METHOD_IMPL_DEFAULT_IMPL =

+      ") {\n" //$NON-NLS-1$ 

+    + IConditionConstants.USER_CODE_BEGINNING_DELIMITER 

+    + "\nreturn true;\n" //$NON-NLS-1$ 

+    + IConditionConstants.USER_CODE_END_DELIMITER 

+    + "\n}\n}"; //$NON-NLS-1$

+  

+  /**

+   * Check real implementation signature prefix.

+   */

+  protected static final String CHECK_METHOD_IMPL_SIGNATURE_PREFIX = "protected boolean check("; //$NON-NLS-1$

+  

+  /**

+   * Check real implementation default comments.

+   */

+  protected static final String CHECK_METHOD_IMPL_DEFAULT_COMMENTS =

+      "/**\n* Check method user implementation.<br>\n* User must implement and comment between delimiters only !\n* Public signature and comments are lost when a merge is performed.\n* " //$NON-NLS-1$ 

+    + IConditionConstants.UNMODIFIABLE_ANNOTATION_TAG 

+    + "\n*/\n"; //$NON-NLS-1$

+  

+  /**

+   * Array access to parameter number N prefix.

+   */

+  protected static final String PARAMETER_N_PREFIX = "parameters_p["; //$NON-NLS-1$

+  

+  /**

+   * End of generic check method code.

+   */

+  protected static final String GENERIC_CHECK_METHOD_END = ");\n}\n\n"; //$NON-NLS-1$

+  

+  /**

+   * Call to check method prefix.

+   */

+  protected static final String CHECK_METHOD_CALL_PREFIX = "return check("; //$NON-NLS-1$

+  

+  /**

+   * Generic check method comments.

+   */

+  protected static final String GENERIC_CHECK_METHOD_COMMENTS =

+      "/**\n* Generated check method.<br>\n* User should left this code untouched for it is lost when a merge is performed.\n* " //$NON-NLS-1$ 

+    + IConditionConstants.UNMODIFIABLE_ANNOTATION_TAG 

+    + "\n*/\n";//$NON-NLS-1$

+  

+  /**

+   * Generic check method signature.

+   */

+  protected static final String GENERIC_CHECK_METHOD_SIGNATURE = 

+    "public boolean check(Object... parameters_p) {\n"; //$NON-NLS-1$

+  

+  /**

+   * Default implementation for generated condition class.

+   */

+  protected static final String DEFAULT_CONDITION_IMPLEMENTATION = 

+      " extends " //$NON-NLS-1$ 

+    + AbstractPatternCondition.class.getSimpleName() 

+    + " {\n"; //$NON-NLS-1$

+  

+  /**

+   * Class comments.

+   */

+  protected static final String CLASS_COMMENTS =

+    "/**\n*Condition class implementation.\n*A merge occurs each time the corresponding pattern parameters are changed.\n*Both check methods are subject to merge (see associated comments).\n*Any other method is left untouched as a result of the merging operation.\n*/\n"; //$NON-NLS-1$

+  

+  /**

+   * Class declaration prefix.

+   */

+  protected static final String CLASS_DECLARATION_PREFIX = "public class "; //$NON-NLS-1$

+  

+  /**

+   * Default import for an implementation of a condition class.

+   */

+  protected static final String DEFAULT_CONDITION_IMPORT = 

+      AbstractPatternCondition.class.getName() 

+    + ";\n\n"; //$NON-NLS-1$

+  

+  /**

+   * Import directive prefix.

+   */

+  protected static final String IMPORT_DIRECTIVE_PREFIX = "import "; //$NON-NLS-1$

+  

+  /**

+   * Import suffix.

+   */

+  protected static final String IMPORT_DIRECTIVE_SUFFIX = ";\n"; //$NON-NLS-1$

+  

+  /**

+   * Package declaration prefix.

+   */

+  protected static final String PACKAGE_DECLARATION_PREFIX = "package "; //$NON-NLS-1$

+  

+  /**

+   * ']' character.

+   */

+  protected static final char SQUARE_BRACKET_CLOSING_CHARACTER = ']';

+

+  /**

+   * Get condition class expected content, without the already existing user code.<br>

+   * This is the condition class as it should be by default for current pattern content.

+   * @param patternData_p

+   * @param parameters_p

+   * @return

+   */

+  public static String getNewConditionClassDefaultContent(PatternData patternData_p, List<ParameterRelation> parameters_p) {

+    StringBuilder result = new StringBuilder();

+    // Add package declaration.

+    result

+      .append(PACKAGE_DECLARATION_PREFIX)

+      .append(PatternConstants.PATTERN_CONDITION_GENERATED_BASE_PACKAGE);

+    result

+      .append(ICommonConstants.SEMICOLON_CHARACTER)

+      .append(ICommonConstants.EOL_CHARACTER)

+      .append(ICommonConstants.EOL_CHARACTER);

+    // Add imports for all parameters.

+    for (ParameterRelation parameterRelation : parameters_p) {

+      EPackage parameterPackage = parameterRelation.getType().getEPackage();

+      String packageImportedName = EcoreHelper.getImportedPackageName(parameterPackage);

+      if (packageImportedName != null) {

+        // Append import directive.

+        result

+          .append(IMPORT_DIRECTIVE_PREFIX)

+          .append(packageImportedName)

+          .append(ICommonConstants.DOT_CHARACTER)

+          .append(parameterRelation.getType().getName())

+          .append(IMPORT_DIRECTIVE_SUFFIX);

+      }

+    }

+    result.append(ICommonConstants.EOL_CHARACTER);

+    // Import parent interface/class.

+    result

+      .append(IMPORT_DIRECTIVE_PREFIX)

+      .append(DEFAULT_CONDITION_IMPORT);

+    // Add class declaration.

+    String className = GeneratedContentProducer.getConditionClassName(patternData_p);

+    result.append(CLASS_COMMENTS);

+    result

+      .append(CLASS_DECLARATION_PREFIX)

+      .append(className)

+      .append(DEFAULT_CONDITION_IMPLEMENTATION);

+    // Add generic check method declaration.

+    result.append(GENERIC_CHECK_METHOD_COMMENTS);

+    result.append(GENERIC_CHECK_METHOD_SIGNATURE);

+    result.append(CHECK_METHOD_CALL_PREFIX);

+    // Parameter position.

+    int i = 0;

+    // True implementation signature.

+    StringBuilder realImplSignature = new StringBuilder();

+    for (Iterator<ParameterRelation> parameters = parameters_p.iterator(); parameters.hasNext(); i++) {

+      ParameterRelation param = parameters.next();

+      String paramTypeName = param.getType().getName();

+      result

+        .append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER)

+        .append(paramTypeName)

+        .append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER);

+      result

+        .append(PARAMETER_N_PREFIX)

+        .append(i)

+        .append(SQUARE_BRACKET_CLOSING_CHARACTER);

+      realImplSignature

+        .append(paramTypeName)

+        .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+        .append(param.getName());

+      if (parameters.hasNext()) {

+        result.append(ICommonConstants.COMMA_CHARACTER);

+        realImplSignature.append(ICommonConstants.COMMA_CHARACTER);

+      }

+    }

+    // Add generic check method end declaration.

+    result.append(GENERIC_CHECK_METHOD_END);

+    // Add real check implementation declaration.

+    result.append(CHECK_METHOD_IMPL_DEFAULT_COMMENTS);

+    result

+      .append(CHECK_METHOD_IMPL_SIGNATURE_PREFIX)

+      .append(realImplSignature.toString())

+      .append(CHECK_METHOD_IMPL_DEFAULT_IMPL);

+    return result.toString();

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/IConditionConstants.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/IConditionConstants.java
new file mode 100644
index 0000000..dc464c7
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/IConditionConstants.java
@@ -0,0 +1,40 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore.condition;

+

+/**

+ * Condition producer and contributors shared constants.

+ * @author Guillaume Brocard

+ */

+public interface IConditionConstants {

+  

+  /**

+   * Condition class name suffix.

+   */

+  public static final String CONDITION_CLASS_NAME_SUFFIX = "Condition"; //$NON-NLS-1$

+  

+  /**

+   * Delimiter that marks the beginning of a not generated code block.

+   */

+  public static final String USER_CODE_BEGINNING_DELIMITER = "// begin-user-code"; //$NON-NLS-1$

+  

+  /**

+   * Delimiter that marks the end of a not generated code block.

+   */

+  public static final String USER_CODE_END_DELIMITER = "// end-user-code"; //$NON-NLS-1$

+  

+  /**

+   * Annotation constant <code>@unmodifiable</code> used to mark methods that are generated and not modifiable by developer except in a specific block delimited by

+   *               {@link #USER_CODE_BEGINNING_DELIMITER} and {@link #USER_CODE_END_DELIMITER}.

+   */

+  public static final String UNMODIFIABLE_ANNOTATION_TAG = "@unmodifiable"; //$NON-NLS-1$

+  

+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/IPatternCondition.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/IPatternCondition.java
new file mode 100644
index 0000000..83414d9
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/condition/IPatternCondition.java
@@ -0,0 +1,44 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.ecore.condition;

+

+import org.eclipse.egf.core.context.ProductionContext;

+

+/**

+ * Pattern condition interface.<br>

+ * Defines a static condition that the pattern parameters should meet so as to select elements for pattern matching.<br>

+ * The parameters instances that meet this condition at runtime are selected as potential entries for the pattern matching.<br>

+ * <b>Internal purpose only.</b><br>

+ * The pattern framework automatically creates a new Java class implementing this interface for each new pattern that requires

+ * a condition between its parameters. The pattern developer is then asked to fill the generated 'check' method content for the condition

+ * definition. The framework automatically generates the content of the {@link #check(Object...)} method, pointing to the check

+ * method filled by the developer.<br>

+ * Eventually, there is to be a merge when pattern parameters have changed between existing check code and new check method signature.

+ * @author brocard

+ */

+public interface IPatternCondition {

+  

+  /**

+   * Check that given parameters meet the pattern condition.<br>

+   * The pattern condition is not supposed to be accessed from the Java code.<br>

+   * Instead use the pattern ui to get full details about the condition.

+   * @param parameters_p

+   * @return

+   */

+  public boolean check(Object... parameters_p);

+

+  /**

+   * Set production context available for this condition.

+   * @param context_p the context to use as available one. <code>null</code> if none.

+   */

+  public void setContext(ProductionContext context_p);

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g
new file mode 100644
index 0000000..7e36aa4
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g
@@ -0,0 +1,19 @@
+grammar PatternLanguage;

+

+options {

+  output=AST;

+  ASTLabelType=CommonTree;

+}

+

+call : operationCall+ ;

+

+operationCall : operationName^ LPAR! PARAM* RPAR! ENDOFCALL! ;

+

+operationName : ('CALL' | 'SUPER' | 'READ' | 'PATTERN') ;

+

+ENDOFCALL : ';' ;

+LPAR : '(' ;

+RPAR : ')' ;

+PARAM : ('a'..'z'|'A'..'Z'|'0'..'9'|'.'|'/'|'#')* ;

+WS    : (' '|'\r'|'\n'|'\t'){$channel=HIDDEN;}

+      ;

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.tokens b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.tokens
new file mode 100644
index 0000000..3f53cbb
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.tokens
@@ -0,0 +1,9 @@
+ENDOFCALL=7
+RPAR=6
+WS=8
+LPAR=4
+PARAM=5
+'PATTERN'=12
+'READ'=11
+'CALL'=9
+'SUPER'=10
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguageLexer.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguageLexer.java
new file mode 100644
index 0000000..eb386ed
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguageLexer.java
@@ -0,0 +1,460 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.ecore.grammar;
+
+// $ANTLR 3.0 ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g 2007-06-28 16:45:58
+
+import org.antlr.runtime.CharStream;
+import org.antlr.runtime.Lexer;
+import org.antlr.runtime.MismatchedSetException;
+import org.antlr.runtime.RecognitionException;
+
+public class PatternLanguageLexer extends Lexer {
+  public static final int ENDOFCALL = 7;
+  public static final int T10 = 10;
+  public static final int RPAR = 6;
+  public static final int T11 = 11;
+  public static final int T9 = 9;
+  public static final int EOF = -1;
+  public static final int WS = 8;
+  public static final int LPAR = 4;
+  public static final int T12 = 12;
+  public static final int Tokens = 13;
+  public static final int PARAM = 5;
+
+  public PatternLanguageLexer(CharStream input_p) {
+    super(input_p);
+  }
+
+  @Override
+  public String getGrammarFileName() {
+    return "./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g";} //$NON-NLS-1$
+
+  // $ANTLR start T9
+  public final void mT9() throws RecognitionException {
+    try {
+      int _type = T9;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:3:6: ( 'CALL' )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:3:6: 'CALL'
+      {
+        match("CALL"); //$NON-NLS-1$
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end T9
+
+  // $ANTLR start T10
+  public final void mT10() throws RecognitionException {
+    try {
+      int _type = T10;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:4:7: ( 'SUPER' )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:4:7: 'SUPER'
+      {
+        match("SUPER"); //$NON-NLS-1$
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end T10
+
+  // $ANTLR start T11
+  public final void mT11() throws RecognitionException {
+    try {
+      int _type = T11;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:5:7: ( 'READ' )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:5:7: 'READ'
+      {
+        match("READ"); //$NON-NLS-1$
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end T11
+
+  // $ANTLR start T12
+  public final void mT12() throws RecognitionException {
+    try {
+      int _type = T12;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:6:7: ( 'PATTERN' )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:6:7: 'PATTERN'
+      {
+        match("PATTERN"); //$NON-NLS-1$
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end T12
+
+  // $ANTLR start ENDOFCALL
+  public final void mENDOFCALL() throws RecognitionException {
+    try {
+      int _type = ENDOFCALL;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:14:13: ( ';' )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:14:13: ';'
+      {
+        match(';');
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end ENDOFCALL
+
+  // $ANTLR start LPAR
+  public final void mLPAR() throws RecognitionException {
+    try {
+      int _type = LPAR;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:15:8: ( '(' )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:15:8: '('
+      {
+        match('(');
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end LPAR
+
+  // $ANTLR start RPAR
+  public final void mRPAR() throws RecognitionException {
+    try {
+      int _type = RPAR;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:16:8: ( ')' )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:16:8: ')'
+      {
+        match(')');
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end RPAR
+
+  // $ANTLR start PARAM
+  public final void mPARAM() throws RecognitionException {
+    try {
+      int _type = PARAM;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:17:9: ( ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '/' | '#' )* )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:17:9: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '/' | '#' )*
+      {
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:17:9: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '/' | '#' )*
+        loop1: do {
+          int alt1 = 2;
+          int LA1_0 = input.LA(1);
+
+          if ((LA1_0 == '#' || (LA1_0 >= '.' && LA1_0 <= '9') || (LA1_0 >= 'A' && LA1_0 <= 'Z') || (LA1_0 >= 'a' && LA1_0 <= 'z'))) {
+            alt1 = 1;
+          }
+
+          switch (alt1) {
+            case 1:
+              // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:
+            {
+              if (input.LA(1) == '#' || (input.LA(1) >= '.' && input.LA(1) <= '9') || (input.LA(1) >= 'A' && input.LA(1) <= 'Z')
+                  || (input.LA(1) >= 'a' && input.LA(1) <= 'z')) {
+                input.consume();
+              } else {
+                MismatchedSetException mse = new MismatchedSetException(null, input);
+                recover(mse);
+                throw mse;
+              }
+            }
+            break;
+
+            default:
+            break loop1;
+          }
+        } while (true);
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end PARAM
+
+  // $ANTLR start WS
+  public final void mWS() throws RecognitionException {
+    try {
+      int _type = WS;
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:18:9: ( ( ' ' | '\\r' | '\\n' | '\\t' ) )
+      // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:18:9: ( ' ' | '\\r' | '\\n' | '\\t' )
+      {
+        if ((input.LA(1) >= '\t' && input.LA(1) <= '\n') || input.LA(1) == '\r' || input.LA(1) == ' ') {
+          input.consume();
+        } else {
+          MismatchedSetException mse = new MismatchedSetException(null, input);
+          recover(mse);
+          throw mse;
+        }
+        channel = HIDDEN;
+      }
+      this.type = _type;
+    } finally {
+      // NTD.
+    }
+  }
+
+  // $ANTLR end WS
+  @Override
+  public void mTokens() throws RecognitionException {
+    // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:10: ( T9 | T10 | T11 | T12 | ENDOFCALL | LPAR | RPAR | PARAM | WS )
+    int alt2 = 9;
+    switch (input.LA(1)) {
+      case 'C': {
+        int LA2_1 = input.LA(2);
+
+        if ((LA2_1 == 'A')) {
+          int LA2_10 = input.LA(3);
+
+          if ((LA2_10 == 'L')) {
+            int LA2_14 = input.LA(4);
+
+            if ((LA2_14 == 'L')) {
+              int LA2_18 = input.LA(5);
+
+              if ((LA2_18 == '#' || (LA2_18 >= '.' && LA2_18 <= '9') || (LA2_18 >= 'A' && LA2_18 <= 'Z') || (LA2_18 >= 'a' && LA2_18 <= 'z'))) {
+                alt2 = 8;
+              } else {
+                alt2 = 1;
+              }
+            } else {
+              alt2 = 8;
+            }
+          } else {
+            alt2 = 8;
+          }
+        } else {
+          alt2 = 8;
+        }
+      }
+      break;
+      case 'S': {
+        int LA2_2 = input.LA(2);
+
+        if ((LA2_2 == 'U')) {
+          int LA2_11 = input.LA(3);
+
+          if ((LA2_11 == 'P')) {
+            int LA2_15 = input.LA(4);
+
+            if ((LA2_15 == 'E')) {
+              int LA2_19 = input.LA(5);
+
+              if ((LA2_19 == 'R')) {
+                int LA2_23 = input.LA(6);
+
+                if ((LA2_23 == '#' || (LA2_23 >= '.' && LA2_23 <= '9') || (LA2_23 >= 'A' && LA2_23 <= 'Z') || (LA2_23 >= 'a' && LA2_23 <= 'z'))) {
+                  alt2 = 8;
+                } else {
+                  alt2 = 2;
+                }
+              } else {
+                alt2 = 8;
+              }
+            } else {
+              alt2 = 8;
+            }
+          } else {
+            alt2 = 8;
+          }
+        } else {
+          alt2 = 8;
+        }
+      }
+      break;
+      case 'R': {
+        int LA2_3 = input.LA(2);
+
+        if ((LA2_3 == 'E')) {
+          int LA2_12 = input.LA(3);
+
+          if ((LA2_12 == 'A')) {
+            int LA2_16 = input.LA(4);
+
+            if ((LA2_16 == 'D')) {
+              int LA2_20 = input.LA(5);
+
+              if ((LA2_20 == '#' || (LA2_20 >= '.' && LA2_20 <= '9') || (LA2_20 >= 'A' && LA2_20 <= 'Z') || (LA2_20 >= 'a' && LA2_20 <= 'z'))) {
+                alt2 = 8;
+              } else {
+                alt2 = 3;
+              }
+            } else {
+              alt2 = 8;
+            }
+          } else {
+            alt2 = 8;
+          }
+        } else {
+          alt2 = 8;
+        }
+      }
+      break;
+      case 'P': {
+        int LA2_4 = input.LA(2);
+
+        if ((LA2_4 == 'A')) {
+          int LA2_13 = input.LA(3);
+
+          if ((LA2_13 == 'T')) {
+            int LA2_17 = input.LA(4);
+
+            if ((LA2_17 == 'T')) {
+              int LA2_21 = input.LA(5);
+
+              if ((LA2_21 == 'E')) {
+                int LA2_25 = input.LA(6);
+
+                if ((LA2_25 == 'R')) {
+                  int LA2_27 = input.LA(7);
+
+                  if ((LA2_27 == 'N')) {
+                    int LA2_28 = input.LA(8);
+
+                    if ((LA2_28 == '#' || (LA2_28 >= '.' && LA2_28 <= '9') || (LA2_28 >= 'A' && LA2_28 <= 'Z') || (LA2_28 >= 'a' && LA2_28 <= 'z'))) {
+                      alt2 = 8;
+                    } else {
+                      alt2 = 4;
+                    }
+                  } else {
+                    alt2 = 8;
+                  }
+                } else {
+                  alt2 = 8;
+                }
+              } else {
+                alt2 = 8;
+              }
+            } else {
+              alt2 = 8;
+            }
+          } else {
+            alt2 = 8;
+          }
+        } else {
+          alt2 = 8;
+        }
+      }
+      break;
+      case ';': {
+        alt2 = 5;
+      }
+      break;
+      case '(': {
+        alt2 = 6;
+      }
+      break;
+      case ')': {
+        alt2 = 7;
+      }
+      break;
+      case '\t':
+      case '\n':
+      case '\r':
+      case ' ': {
+        alt2 = 9;
+      }
+      break;
+      default:
+        alt2 = 8;
+    }
+
+    switch (alt2) {
+      case 1:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:10: T9
+      {
+        mT9();
+
+      }
+      break;
+      case 2:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:13: T10
+      {
+        mT10();
+
+      }
+      break;
+      case 3:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:17: T11
+      {
+        mT11();
+
+      }
+      break;
+      case 4:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:21: T12
+      {
+        mT12();
+
+      }
+      break;
+      case 5:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:25: ENDOFCALL
+      {
+        mENDOFCALL();
+
+      }
+      break;
+      case 6:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:35: LPAR
+      {
+        mLPAR();
+
+      }
+      break;
+      case 7:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:40: RPAR
+      {
+        mRPAR();
+
+      }
+      break;
+      case 8:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:45: PARAM
+      {
+        mPARAM();
+
+      }
+      break;
+      case 9:
+        // ./src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage.g:1:51: WS
+      {
+        mWS();
+
+      }
+      break;
+
+    }
+
+  }
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguageParser.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguageParser.java
new file mode 100644
index 0000000..79b5df9
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguageParser.java
@@ -0,0 +1,294 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.ecore.grammar;
+
+// $ANTLR 3.0 ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g 2007-06-28 16:45:58
+
+import org.antlr.runtime.BitSet;
+import org.antlr.runtime.EarlyExitException;
+import org.antlr.runtime.MismatchedSetException;
+import org.antlr.runtime.Parser;
+import org.antlr.runtime.ParserRuleReturnScope;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.Token;
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.tree.CommonTree;
+import org.antlr.runtime.tree.CommonTreeAdaptor;
+import org.antlr.runtime.tree.TreeAdaptor;
+
+public class PatternLanguageParser extends Parser {
+  public static final String[] tokenNames =
+                                            new String[] {
+                                                          "<invalid>", "<EOR>", "<DOWN>", "<UP>", "LPAR", "PARAM", "RPAR", "ENDOFCALL", "WS", "'CALL'", "'SUPER'", "'READ'", "'PATTERN'" //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$//$NON-NLS-13$
+                                            };
+  public static final int ENDOFCALL = 7;
+  public static final int RPAR = 6;
+  public static final int WS = 8;
+  public static final int EOF = -1;
+  public static final int LPAR = 4;
+  public static final int PARAM = 5;
+
+  public PatternLanguageParser(TokenStream input_p) {
+    super(input_p);
+  }
+
+  protected TreeAdaptor adaptor = new CommonTreeAdaptor();
+
+  public void setTreeAdaptor(TreeAdaptor adaptor_p) {
+    this.adaptor = adaptor_p;
+  }
+
+  public TreeAdaptor getTreeAdaptor() {
+    return adaptor;
+  }
+
+  @Override
+  public String[] getTokenNames() {
+    return tokenNames;
+  }
+
+  @Override
+  public String getGrammarFileName() {
+    return "./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g"; //$NON-NLS-1$
+  }
+
+  public static class call_return extends ParserRuleReturnScope {
+    CommonTree tree;
+
+    @Override
+    public Object getTree() {
+      return tree;
+    }
+  }
+
+  // $ANTLR start call
+  // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:8:1: call : ( operationCall )+ ;
+  public final call_return call() throws RecognitionException {
+    call_return retval = new call_return();
+    retval.start = input.LT(1);
+
+    CommonTree root_0 = null;
+
+    operationCall_return operationCall1 = null;
+
+    try {
+      // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:8:8: ( ( operationCall )+ )
+      // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:8:8: ( operationCall )+
+      {
+        root_0 = (CommonTree) adaptor.nil();
+
+        // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:8:8: ( operationCall )+
+        int cnt1 = 0;
+        loop1: do {
+          int alt1 = 2;
+          int LA1_0 = input.LA(1);
+
+          if (((LA1_0 >= 9 && LA1_0 <= 12))) {
+            alt1 = 1;
+          }
+
+          switch (alt1) {
+            case 1:
+              // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:8:8: operationCall
+            {
+              pushFollow(FOLLOW_operationCall_in_call29);
+              operationCall1 = operationCall();
+              _fsp--;
+
+              adaptor.addChild(root_0, operationCall1.getTree());
+
+            }
+            break;
+
+            default:
+              if (cnt1 >= 1)
+                break loop1;
+              EarlyExitException eee = new EarlyExitException(1, input);
+              throw eee;
+          }
+          cnt1++;
+        } while (true);
+
+      }
+
+      retval.stop = input.LT(-1);
+
+      retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
+      adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+    } catch (RecognitionException re) {
+      reportError(re);
+      recover(input, re);
+    } finally {
+      // NTD.
+    }
+    return retval;
+  }
+
+  // $ANTLR end call
+
+  public static class operationCall_return extends ParserRuleReturnScope {
+    CommonTree tree;
+
+    @Override
+    public Object getTree() {
+      return tree;
+    }
+  }
+
+  // $ANTLR start operationCall
+  // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:10:1: operationCall : operationName LPAR ( PARAM )* RPAR ENDOFCALL ;
+  @SuppressWarnings("unused")
+  public final operationCall_return operationCall() throws RecognitionException {
+    operationCall_return retval = new operationCall_return();
+    retval.start = input.LT(1);
+
+    CommonTree root_0 = null;
+
+    Token LPAR3 = null;
+    Token PARAM4 = null;
+    Token RPAR5 = null;
+    Token ENDOFCALL6 = null;
+    operationName_return operationName2 = null;
+
+    CommonTree LPAR3_tree = null;
+    CommonTree PARAM4_tree = null;
+    CommonTree RPAR5_tree = null;
+    CommonTree ENDOFCALL6_tree = null;
+
+    try {
+      // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:10:17: ( operationName LPAR ( PARAM )* RPAR ENDOFCALL )
+      // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:10:17: operationName LPAR ( PARAM )* RPAR ENDOFCALL
+      {
+        root_0 = (CommonTree) adaptor.nil();
+
+        pushFollow(FOLLOW_operationName_in_operationCall39);
+        operationName2 = operationName();
+        _fsp--;
+
+        root_0 = (CommonTree) adaptor.becomeRoot(operationName2.getTree(), root_0);
+        LPAR3 = input.LT(1);
+        match(input, LPAR, FOLLOW_LPAR_in_operationCall42);
+        // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:10:38: ( PARAM )*
+        loop2: do {
+          int alt2 = 2;
+          int LA2_0 = input.LA(1);
+
+          if ((LA2_0 == PARAM)) {
+            alt2 = 1;
+          }
+
+          switch (alt2) {
+            case 1:
+              // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:10:38: PARAM
+            {
+              PARAM4 = input.LT(1);
+              match(input, PARAM, FOLLOW_PARAM_in_operationCall45);
+              PARAM4_tree = (CommonTree) adaptor.create(PARAM4);
+              adaptor.addChild(root_0, PARAM4_tree);
+
+            }
+            break;
+
+            default:
+            break loop2;
+          }
+        } while (true);
+
+        RPAR5 = input.LT(1);
+        match(input, RPAR, FOLLOW_RPAR_in_operationCall48);
+        ENDOFCALL6 = input.LT(1);
+        match(input, ENDOFCALL, FOLLOW_ENDOFCALL_in_operationCall51);
+
+      }
+
+      retval.stop = input.LT(-1);
+
+      retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
+      adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+    } catch (RecognitionException re) {
+      reportError(re);
+      recover(input, re);
+    } finally {
+      // NTD.
+    }
+    return retval;
+  }
+
+  // $ANTLR end operationCall
+
+  public static class operationName_return extends ParserRuleReturnScope {
+    CommonTree tree;
+
+    @Override
+    public Object getTree() {
+      return tree;
+    }
+  }
+
+  // $ANTLR start operationName
+  // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:12:1: operationName : ( 'CALL' | 'SUPER' | 'READ' | 'PATTERN' ) ;
+  @SuppressWarnings("unused")
+  public final operationName_return operationName() throws RecognitionException {
+    operationName_return retval = new operationName_return();
+    retval.start = input.LT(1);
+
+    CommonTree root_0 = null;
+
+    Token set7 = null;
+
+    CommonTree set7_tree = null;
+
+    try {
+      // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:12:17: ( ( 'CALL' | 'SUPER' | 'READ' | 'PATTERN' ) )
+      // ./src/org/eclipse/egf/pattern/pattern/ecore/grammar/PatternLanguage.g:12:17: ( 'CALL' | 'SUPER' | 'READ' | 'PATTERN' )
+      {
+        root_0 = (CommonTree) adaptor.nil();
+
+        set7 = input.LT(1);
+        if ((input.LA(1) >= 9 && input.LA(1) <= 12)) {
+          input.consume();
+          adaptor.addChild(root_0, adaptor.create(set7));
+          errorRecovery = false;
+        } else {
+          MismatchedSetException mse = new MismatchedSetException(null, input);
+          recoverFromMismatchedSet(input, mse, FOLLOW_set_in_operationName61);
+          throw mse;
+        }
+
+      }
+
+      retval.stop = input.LT(-1);
+
+      retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
+      adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+    } catch (RecognitionException re) {
+      reportError(re);
+      recover(input, re);
+    } finally {
+      // NTD.
+    }
+    return retval;
+  }
+
+  // $ANTLR end operationName
+
+  public static final BitSet FOLLOW_operationCall_in_call29 = new BitSet(new long[] { 0x0000000000001E02L });
+  public static final BitSet FOLLOW_operationName_in_operationCall39 = new BitSet(new long[] { 0x0000000000000010L });
+  public static final BitSet FOLLOW_LPAR_in_operationCall42 = new BitSet(new long[] { 0x0000000000000060L });
+  public static final BitSet FOLLOW_PARAM_in_operationCall45 = new BitSet(new long[] { 0x0000000000000060L });
+  public static final BitSet FOLLOW_RPAR_in_operationCall48 = new BitSet(new long[] { 0x0000000000000080L });
+  public static final BitSet FOLLOW_ENDOFCALL_in_operationCall51 = new BitSet(new long[] { 0x0000000000000002L });
+  public static final BitSet FOLLOW_set_in_operationName61 = new BitSet(new long[] { 0x0000000000000002L });
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage__.g b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage__.g
new file mode 100644
index 0000000..eecaa90
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/PatternLanguage__.g
@@ -0,0 +1,18 @@
+lexer grammar PatternLanguage;
+
+T9 : 'CALL' ;
+T10 : 'SUPER' ;
+T11 : 'READ' ;
+T12 : 'PATTERN' ;
+
+// $ANTLR src "./src/com/thalesgroup/mde/mdsofa/asset/pattern/ecore/grammar/PatternLanguage.g" 14
+ENDOFCALL : ';' ;

+// $ANTLR src "./src/com/thalesgroup/mde/mdsofa/asset/pattern/ecore/grammar/PatternLanguage.g" 15
+LPAR : '(' ;

+// $ANTLR src "./src/com/thalesgroup/mde/mdsofa/asset/pattern/ecore/grammar/PatternLanguage.g" 16
+RPAR : ')' ;

+// $ANTLR src "./src/com/thalesgroup/mde/mdsofa/asset/pattern/ecore/grammar/PatternLanguage.g" 17
+PARAM : ('a'..'z'|'A'..'Z'|'0'..'9'|'.'|'/'|'#')* ;

+// $ANTLR src "./src/com/thalesgroup/mde/mdsofa/asset/pattern/ecore/grammar/PatternLanguage.g" 18
+WS    : (' '|'\r'|'\n'|'\t'){$channel=HIDDEN;}

+      ;

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/TestGrammar.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/TestGrammar.java
new file mode 100644
index 0000000..dd22a42
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/grammar/TestGrammar.java
@@ -0,0 +1,56 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.ecore.grammar;

+

+import org.antlr.runtime.ANTLRStringStream;

+import org.antlr.runtime.CharStream;

+import org.antlr.runtime.CommonTokenStream;

+import org.antlr.runtime.tree.CommonTree;

+import org.antlr.runtime.tree.Tree;

+

+/**

+ * @author brocard

+ *

+ */

+public class TestGrammar {

+  /**

+   * @param args

+   */

+  public static void main(String[] args) throws Exception {

+    CharStream in = new ANTLRStringStream("READ(/org.eclipse.egf.pattern.helloworld/templates/helloworld/helloWorld.jet);PATTERN(library1.pattern1#helloworld);CALL(helloworld);SUPER();"); //$NON-NLS-1$

+    PatternLanguageLexer lexer = new PatternLanguageLexer(in);

+    CommonTokenStream tokens = new CommonTokenStream(lexer);

+    PatternLanguageParser parser = new PatternLanguageParser(tokens);

+    CommonTree tree = (CommonTree) parser.call().getTree();

+    System.out.println(tree.toStringTree());

+    explore(tree, 0);

+  }

+

+  /**

+   * Explore tree.

+   * @param tree_p

+   */

+  protected static void explore(Tree tree_p, int tabCount_p) {

+    if (null == tree_p) {

+      return;

+    }

+    int childCount = tree_p.getChildCount();

+    int tabCount = tabCount_p + 2;

+    for (int i = 0; i < childCount; i++) {

+      Tree childTree = tree_p.getChild(i);

+      for (int j = 0; j < tabCount; j++) {

+        System.out.print(" "); //$NON-NLS-1$

+      }

+      System.out.println(childTree.getText());

+      explore(childTree, tabCount);

+    }

+  }

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/messages.properties b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/messages.properties
new file mode 100644
index 0000000..21a1e3f
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/ecore/messages.properties
@@ -0,0 +1,11 @@
+###############################################################################

+#  Copyright (c) 2009 Thales Corporate Services S.A.S.

+#  All rights reserved. This program and the accompanying materials

+#  are made available under the terms of the Eclipse Public License v1.0

+#  which accompanies this distribution, and is available at

+#  http://www.eclipse.org/legal/epl-v10.html

+# 

+#  Contributors:

+#      Thales Corporate Services S.A.S - initial API and implementation

+###############################################################################

+PatternHandler_AutoGeneratedDescriptionText=Auto-generated description for {0}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/execution/IPatternExecutionReporter.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/execution/IPatternExecutionReporter.java
new file mode 100644
index 0000000..39ac179
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/execution/IPatternExecutionReporter.java
@@ -0,0 +1,41 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.execution;

+

+import java.util.Map;

+

+import org.eclipse.egf.core.context.ProductionContext;

+import org.eclipse.emf.ecore.EObject;

+

+

+/**

+ * Classes which implement this interface provide a method<br>

+ * that deals with the event that is generated when a pattern execution is finished.<br>

+ * Implementors must provide a default constructor.

+ * @author Guillaume Brocard

+ */

+public interface IPatternExecutionReporter {

+  /**

+   * Sent when a pattern overall execution has just finished.

+   * @param patternFullId_p the full identifier of the pattern that the execution is finished for.

+   * @param output_p the output resulting from the pattern execution.

+   */

+  public void patternExecutionFinished(String output_p, String patternFullId_p, ProductionContext context_p);

+

+  /**

+   * Sent when a pattern loop execution is finished.

+   * @param output_p The loop output.

+   * @param patternFullId_p The full id of the pattern that declares the loop.

+   * @param context_p The production context of the pattern execution.

+   * @param tuple_p The contextual loop tuple. This object should not be kept by the implementor for it is used for every possible tuple values.

+   */

+  public void patternLoopExecutionFinished(String output_p, String patternFullId_p, ProductionContext context_p, Map<String, EObject> tuple_p);

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/execution/PatternExecutionHelper.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/execution/PatternExecutionHelper.java
new file mode 100644
index 0000000..63a447b
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/execution/PatternExecutionHelper.java
@@ -0,0 +1,134 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.execution;

+

+import java.util.Map;

+

+import org.apache.log4j.Logger;

+import org.eclipse.core.runtime.IConfigurationElement;

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.constant.IPatternTemplateConstants;

+import org.eclipse.egf.common.helper.ExtensionPointHelper;

+import org.eclipse.egf.core.context.ProductionContext;

+import org.eclipse.egf.pattern.production.TemplateType;

+import org.eclipse.egf.pattern.production.jet.IGenerator;

+import org.eclipse.emf.ecore.resource.Resource;

+

+

+/**

+ * @author Guillaume Brocard

+ */

+public class PatternExecutionHelper {

+  

+  /**

+   * Log4j reference logger.

+   */

+  private static final Logger __logger = Logger.getLogger(PatternExecutionHelper.class.getPackage().getName());

+

+  /**

+   * Argument key.<br>

+   * Used as a key in the argument map.

+   * @author Guillaume Brocard

+   */

+  public static enum ArgumentKey {

+    EMF_RESOURCE, PRODUCTION_CONTEXT, EXECUTION_REPORTER

+  }

+

+  /**

+   * Get argument value for given key.

+   * @param argument_p

+   * @param key_p

+   * @return

+   */

+  @SuppressWarnings("unchecked")

+  private static Object getValue(Object argument_p, ArgumentKey key_p) {

+    Object result = null;

+    if (argument_p instanceof Map) {

+      Map<ArgumentKey, Object> arguments = (Map<ArgumentKey, Object>) argument_p;

+      result = arguments.get(key_p);

+    }

+    return result;

+  }

+

+  /**

+   * Get EMF resource from pattern argument.

+   * @param argument_p

+   * @return

+   */

+  public static Resource getResource(Object argument_p) {

+    return (Resource) getValue(argument_p, ArgumentKey.EMF_RESOURCE);

+  }

+

+  /**

+   * Get production context from pattern argument.

+   * @param argument_p

+   * @return

+   */

+  public static ProductionContext getContext(Object argument_p) {

+    return (ProductionContext) getValue(argument_p, ArgumentKey.PRODUCTION_CONTEXT);

+  }

+

+  /**

+   * Get execution reporter.

+   * @param argument_p

+   * @return

+   */

+  public static IPatternExecutionReporter getExecutionReporter(Object argument_p) {

+    return (IPatternExecutionReporter) getValue(argument_p, ArgumentKey.EXECUTION_REPORTER);

+  }

+

+  /**

+   * Invoke identified pattern with given arguments.

+   * @param patternFullId_p the pattern full id.

+   * @param arguments_p a set of arguments, compatible with the pattern kind.

+   * @return The resulting content of the pattern invocation.

+   */

+  public static Object invokePattern(String patternFullId_p, Object arguments_p) {

+    Object result = ICommonConstants.EMPTY_STRING;

+    try {

+      result = doRunPattern(patternFullId_p, arguments_p);

+    } catch (Exception exception_p) {

+      StringBuilder loggerMessage = new StringBuilder("PatternElementRunnerTask.invokePattern(..) _ "); //$NON-NLS-1$

+      __logger.warn(loggerMessage.toString(), exception_p);

+    }

+    return result;

+  }

+

+  /**

+   * Do run identified pattern with given arguments_p.

+   * @param patternFullId_p the pattern full id.

+   * @param arguments_p a set of arguments, compatible with the pattern kind.

+   * @return The resulting content of the pattern execution.

+   * @throws Exception run failed.

+   */

+  public static Object doRunPattern(String patternFullId_p, Object arguments_p) throws Exception {

+    Object result = ICommonConstants.EMPTY_STRING;

+    // Get the configuration element for given pattern.

+    IConfigurationElement patternConfigElement = ExtensionPointHelper.getConfigurationElement(

+      IPatternTemplateConstants.PATTERN_PLUGIN_ID,

+      IPatternTemplateConstants.PATTERN_TEMPLATE_EXTENSION_POINT_ID,

+      patternFullId_p

+    );

+    if (null != patternConfigElement) {

+      // Get the template engine type.

+      String templateEngineType = patternConfigElement.getAttribute(IPatternTemplateConstants.PATTERN_TEMPLATE_ATT_TYPE);

+      if (TemplateType.JET.getId().equals(templateEngineType)) {

+        // JET template engine is selected, let's load the template code.

+        // The template code is a compiled class that implements IGenerator.

+        IGenerator templateCode = (IGenerator) patternConfigElement.createExecutableExtension(IPatternTemplateConstants.PATTERN_TEMPLATE_ATT_CLASS);

+        // Execute the template

+        result = templateCode.generate(arguments_p);

+      }

+    }

+    return result;

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/ConditionMergeHelper.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/ConditionMergeHelper.java
new file mode 100644
index 0000000..67167eb
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/ConditionMergeHelper.java
@@ -0,0 +1,108 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.internal;

+

+import static org.eclipse.egf.pattern.ecore.condition.IConditionConstants.USER_CODE_BEGINNING_DELIMITER;

+import static org.eclipse.egf.pattern.ecore.condition.IConditionConstants.USER_CODE_END_DELIMITER;

+

+import java.io.ByteArrayInputStream;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.StringHelper;

+import org.eclipse.egf.pattern.PatternActivator;

+import org.eclipse.emf.codegen.merge.java.JControlModel;

+import org.eclipse.emf.codegen.merge.java.JMerger;

+import org.eclipse.emf.codegen.merge.java.facade.ast.ASTFacadeHelper;

+import org.eclipse.emf.common.util.URI;

+

+

+/**

+ * Helper to merge easily merge previous condition generation with new ones.

+ * @author Guillaume Brocard

+ */

+public class ConditionMergeHelper {

+  

+  private ConditionMergeHelper() {

+    // Prevent Instantiation

+  }

+  

+  /**

+   * Merge given new content with given previous one.

+   * @param newContent_p the new content to merge.

+   * @param previousContent_p the previous content to merge

+   * @return the merged content.

+   */

+  public static String merge(String newContent_p, String previousContent_p) {

+    String mergedContent = ICommonConstants.EMPTY_STRING;

+    // Initialize a merger.

+    JMerger merger = getJMerger();

+    // Set as source the new content.

+    merger.setSourceCompilationUnit(merger.createCompilationUnitForContents(newContent_p));

+    // Set as target the previous content.

+    ByteArrayInputStream previousContentInputStream = new ByteArrayInputStream(previousContent_p.getBytes());

+    merger.setTargetCompilationUnit(merger.createCompilationUnitForInputStream(previousContentInputStream));

+    // Merge the source with the target.

+    merger.merge();

+    // Get the merged content.

+    mergedContent = merger.getTargetCompilationUnit().getContents();

+    // Extract the previous user-code between delimiters.

+    String previousDelimitedContent = StringHelper.substring(

+      USER_CODE_BEGINNING_DELIMITER, 

+      USER_CODE_END_DELIMITER, 

+      previousContent_p, 

+      true

+    );

+    // If successfully extracted, let's continue.

+    if (previousDelimitedContent != null) {

+      // Extract the user-code between delimiters.

+      String newDelimitedContent = StringHelper.substring(

+        USER_CODE_BEGINNING_DELIMITER, 

+        USER_CODE_END_DELIMITER, 

+        mergedContent, 

+        true

+      );

+      // If delimited contents are different ones, replace newDelimitedContent in merged content with the previous one.

+      // Developers won't happy to lose their code.

+      if (previousDelimitedContent.equals(newDelimitedContent) == false) {

+        mergedContent = mergedContent.replace(newDelimitedContent, previousDelimitedContent);

+      }

+    }

+    return mergedContent;

+  }

+

+  /**

+   * Creates and initializes a new JMerger

+   * @return JMerger

+   */

+  private static JMerger getJMerger() {

+    // Get the merge file URL.

+    URI mergeFileURI = FileHelper.getFileFullUri(getRelativePathToMergeFile());

+    // Install a JControlModel.

+    JControlModel controlModel = new JControlModel();

+    controlModel.initialize(new ASTFacadeHelper(), mergeFileURI.toString());

+    JMerger jmerger = new JMerger(controlModel);

+    return jmerger;

+  }

+

+  /**

+   * Get merge.xml file relative path to workspace.<br>

+   * Default implementation points to pattern condition class merge file.

+   * @return

+   */

+  protected static String getRelativePathToMergeFile() {

+    return new StringBuilder(ICommonConstants.SLASH_CHARACTER)

+      .append(PatternActivator.getDefault().getPluginID())

+      .append("/resources/merge.xml") //$NON-NLS-1$

+      .toString();

+  }

+  

+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/PatternRegistry.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/PatternRegistry.java
new file mode 100644
index 0000000..2da0e96
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/PatternRegistry.java
@@ -0,0 +1,60 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.internal;

+

+import java.util.HashMap;

+import java.util.Map;

+

+import org.eclipse.core.resources.IProject;

+import org.eclipse.egf.common.constant.IPatternConstants;

+import org.eclipse.egf.common.descriptor.IDescriptor;

+import org.eclipse.egf.common.helper.ExtensionPointHelper;

+import org.eclipse.egf.pde.pattern.reader.WorkspacePatternExtensionReader;

+

+public class PatternRegistry {

+  

+  public static Map<String, IDescriptor> getPatterns(IProject project_p) {

+    // Check

+    if (project_p == null) {

+      return null;

+    }

+    Map<String, IDescriptor> patterns = new HashMap<String, IDescriptor>();

+    // Load root descriptor           

+    IDescriptor rootDescriptor = new WorkspacePatternExtensionReader().getPatternLibraries(project_p);

+    if (rootDescriptor != null) {

+      // Load available patterns in this project

+      getPatterns(patterns, rootDescriptor);

+    }

+    return patterns;

+  }

+  

+  private static void getPatterns(Map<String, IDescriptor> patterns_p, IDescriptor descriptor_p) {

+    // Check

+    if (patterns_p == null || descriptor_p == null) {

+      return;

+    }

+    // Pattern Type

+    if (IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_PATTERN.equals(descriptor_p.getValue(IPatternConstants.PATTERN_EXTENSION_POINT_CHILD_TYPE))) {

+      // Pattern analysis

+      String shortID = (String) descriptor_p.getValue(ExtensionPointHelper.ATT_ID);

+      if (shortID != null && shortID.trim().length() > 0) {

+        patterns_p.put(shortID, descriptor_p);

+      }

+    } else {

+      // Children analysis

+      for (IDescriptor childDescriptor : descriptor_p.getChildren()) {

+        getPatterns(patterns_p, childDescriptor);

+      }      

+    }

+    return;

+  }  

+

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/PatternTemplateRegistry.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/PatternTemplateRegistry.java
new file mode 100644
index 0000000..b3356a2
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/PatternTemplateRegistry.java
@@ -0,0 +1,60 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.internal;

+

+import java.util.HashMap;

+import java.util.Map;

+

+import org.eclipse.core.resources.IProject;

+import org.eclipse.egf.common.constant.IPatternTemplateConstants;

+import org.eclipse.egf.common.descriptor.IDescriptor;

+import org.eclipse.egf.common.helper.ExtensionPointHelper;

+import org.eclipse.egf.pde.pattern.reader.WorkspacePatternTemplateExtensionReader;

+

+public class PatternTemplateRegistry {

+  

+  public static Map<String, IDescriptor> getPatternTemplates(IProject project_p) {

+    // Check

+    if (project_p == null) {

+      return null;

+    }

+    Map<String, IDescriptor> patterns = new HashMap<String, IDescriptor>();

+    // Load root descriptor           

+    IDescriptor rootDescriptor = new WorkspacePatternTemplateExtensionReader().getPatternTemplates(project_p);

+    if (rootDescriptor != null) {

+      // Load available patterns in this project

+      getPatternTemplates(patterns, rootDescriptor);

+    }

+    return patterns;

+  }

+  

+  private static void getPatternTemplates(Map<String, IDescriptor> patterns_p, IDescriptor descriptor_p) {

+    // Check

+    if (patterns_p == null || descriptor_p == null) {

+      return;

+    }

+    // Pattern Type

+    if (IPatternTemplateConstants.PATTERN_TEMPLATE_EXTENSION_POINT_CHILD_PATTERN_TEMPLATE.equals(descriptor_p.getValue(IPatternTemplateConstants.PATTERN_TEMPLATE_EXTENSION_POINT_CHILD_TYPE))) {

+      // Pattern analysis

+      String shortID = (String) descriptor_p.getValue(ExtensionPointHelper.ATT_ID);

+      if (shortID != null && shortID.trim().length() > 0) {

+        patterns_p.put(shortID, descriptor_p);

+      }

+    } else {

+      // Children analysis

+      for (IDescriptor childDescriptor : descriptor_p.getChildren()) {

+        getPatternTemplates(patterns_p, childDescriptor);

+      }      

+    }

+    return;

+  }  

+

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/builders/PatternBuilder.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/builders/PatternBuilder.java
new file mode 100644
index 0000000..ee6069e
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/builders/PatternBuilder.java
@@ -0,0 +1,348 @@
+/**
+ * <copyright>
+ *
+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *      Thales Corporate Services S.A.S - Initial API and implementation
+ *      Soyatec - Contribution
+ *
+ * </copyright>
+ * 
+ */
+
+package org.eclipse.egf.pattern.internal.builders;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.osgi.util.NLS;
+
+import org.eclipse.egf.common.constant.IPatternConstants;
+import org.eclipse.egf.common.descriptor.IDescriptor;
+import org.eclipse.egf.common.helper.FileHelper;
+import org.eclipse.egf.common.helper.MathHelper;
+import org.eclipse.egf.console.EGFConsolePlugin;
+import org.eclipse.egf.pattern.PatternActivator;
+import org.eclipse.egf.pattern.ecore.PatternConstants;
+import org.eclipse.egf.pattern.ecore.PatternHandler;
+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;
+import org.eclipse.egf.pattern.internal.PatternRegistry;
+import org.eclipse.egf.pattern.production.PatternProducer;
+
+
+public class PatternBuilder extends IncrementalProjectBuilder {
+  
+  private static boolean DEBUG = PatternActivator.getDefault().isDebugging();
+  
+  private static IProject[] EMPTY_LIST = new IProject [0];
+
+  private PatternVisitor _patternVisitor = new PatternVisitor();
+        
+  private IJavaProject _javaProject;
+    
+  private Map<String, IDescriptor> _patterns;
+  
+  class PatternVisitor implements IResourceDeltaVisitor {
+    
+    private Collection<IDescriptor> _rebuildPatternModel = new ArrayList<IDescriptor>();    
+    
+    private Collection<IDescriptor> _rebuildFactoryComponent = new ArrayList<IDescriptor>();    
+    
+    private Collection<IDescriptor> _produce = new ArrayList<IDescriptor>();   
+
+    public boolean visit(IResourceDelta delta) throws CoreException {
+      if (delta == null) {
+        return false;
+      }
+      int kind = delta.getKind();
+      IResource resource = delta.getResource();
+      // Process Pattern Model and Pattern Method file extension
+      if (resource.getType() == IResource.FILE) {
+        if (PatternConstants.PATTERN_MODEL_FILE_EXTENSION.equals(resource.getFileExtension())) {
+          // Process Pattern Model          
+          // Looking for an existing descriptor
+          IDescriptor descriptor = getPatterns().get(resource.getFullPath().removeFileExtension().lastSegment());
+          if (descriptor == null) {
+            return false;
+          }        
+          String model = (String) descriptor.getValue(IPatternConstants.PATTERN_MODEL_ATTRIBUTE_NAME);
+          if (model == null || model.trim().length() == 0) {
+            return false;
+          }
+          // Check if the model attribute match an existing workspace resource
+          IResource modelResource = FileHelper.getPlatformResource(new Path(model));
+          if (modelResource == null || modelResource.equals(resource) == false) {
+            return false;
+          }
+          if (kind == IResourceDelta.REMOVED) {
+            _rebuildFactoryComponent.add(descriptor);
+          }
+          if (kind == IResourceDelta.ADDED || kind == IResourceDelta.CHANGED) {
+            _produce.add(descriptor);
+          }
+        } else if (PatternConstants.PATTERN_METHOD_FILE_EXTENSION.equals(resource.getFileExtension())) {
+          // Process Pattern Method          
+          // Looking for an existing descriptor
+          IDescriptor descriptor = getPatterns().get(resource.getParent().getFullPath().lastSegment());
+          if (descriptor == null) {
+            return false;
+          }        
+          // Pattern Methods are described in the Pattern Model
+          // Deeper analysis should be done
+          if (kind == IResourceDelta.REMOVED) {              
+            _rebuildPatternModel.add(descriptor);
+          }
+          // Added are ignored as they cannot appear magically in the pattern model
+          if (kind == IResourceDelta.CHANGED) {
+            _produce.add(descriptor);
+          }          
+        }
+        return false;
+      }
+      return true;
+    }
+
+    public void reset() {
+      _produce.clear();
+      _rebuildPatternModel.clear();        
+      _rebuildFactoryComponent.clear();      
+    }
+
+    public Collection<IDescriptor> getProduce() {
+      return _produce;
+    }
+    
+    public Collection<IDescriptor> getRebuildFactoryComponent() {
+      return _rebuildFactoryComponent;
+    }
+    
+    public Collection<IDescriptor> getRebuildPatternModel() {
+      return _rebuildPatternModel;
+    }        
+
+  }
+
+  @SuppressWarnings("unchecked")
+  protected IProject[] build(int kind_p, Map args_p, IProgressMonitor monitor_p) throws CoreException {
+    // Initialize   
+    if (initialize(monitor_p) == false) {
+      return EMPTY_LIST;
+    }
+    // Let's build our delta
+    try {
+      IResourceDelta delta = getDelta(_javaProject.getProject());    
+      if (kind_p != FULL_BUILD || delta != null) {
+        if (delta.getKind() != IResourceDelta.NO_CHANGE) {
+          // Visit delta
+          _patternVisitor.reset();
+          delta.accept(_patternVisitor);
+          // Rebuild FactoryComponent
+          rebuildFactoryComponent(_patternVisitor.getRebuildFactoryComponent());
+          // Rebuild PatternModel
+          rebuildPatternModel(_patternVisitor.getRebuildPatternModel());          
+          // Produce
+          produce(_patternVisitor.getProduce(), monitor_p);          
+        }
+      } else {
+        // Produce All available Pattern Model
+        produce(getPatterns().values(), monitor_p);        
+      }
+    } finally {
+      cleanup();
+    }
+    // Nothing to return yet
+    return EMPTY_LIST;
+  }
+      
+  protected void produce(Collection<IDescriptor> descriptors_p, IProgressMonitor monitor_p) {
+    if (descriptors_p == null) {
+      return;
+    }
+    // Debug Stuff
+    int rank = 1;
+    long start = System.currentTimeMillis();
+    long stepStart = start;
+    // Produce
+    for (IDescriptor descriptor : descriptors_p) {
+      String definition = (String) descriptor.getValue(IPatternConstants.PATTERN_MODEL_ATTRIBUTE_NAME);
+      if (definition == null || definition.trim().length() == 0) {
+        continue;
+      }
+      PatternHandler patternHandler = new PatternHandler(true);
+      try {        
+        PatternData patternData = patternHandler.load(definition);
+        if (patternData != null) {
+          PatternProducer.producePatterns(patternData.getPattern().getId(), monitor_p);
+          long stepStop = System.currentTimeMillis();
+          if (DEBUG) {
+            EGFConsolePlugin.getConsole().logInfo(
+              NLS.bind(
+                "Produce Pattern Model ''{0}'', step {1}/{2}", //$NON-NLS-1$ 
+                new Object[] {
+                  definition,
+                  rank++,
+                  descriptors_p.size()
+                }
+              )
+            );
+            EGFConsolePlugin.getConsole().logWarning(
+              NLS.bind(
+                "Total elapsed {0}, Step elapsed {1}", //$NON-NLS-1$ 
+                MathHelper.formatAsDuration(stepStop - start),                  
+                MathHelper.formatAsDuration(stepStop - stepStart)
+              ),
+              1
+            );            
+            stepStart = System.currentTimeMillis();
+          }             
+        }
+      } catch (Throwable t) {
+        if (DEBUG) {
+          EGFConsolePlugin.getConsole().logThrowable(
+            NLS.bind(
+              "Unable to load Pattern Model ''{0}''", //$NON-NLS-1$ 
+              definition
+            ), 
+            t
+          );
+        }
+        PatternActivator.getDefault().log(t);
+        continue;
+      } finally {
+        // Check Monitor
+        if (monitor_p.isCanceled()) {
+          break;
+        }
+      }
+    }
+  }  
+  
+  protected void rebuildFactoryComponent(Collection<IDescriptor> descriptors_p) {
+    if (descriptors_p == null) {
+      return;
+    }
+    for (IDescriptor descriptor : descriptors_p) {
+      String definition = (String) descriptor.getValue(IPatternConstants.PATTERN_MODEL_ATTRIBUTE_NAME);
+      if (definition == null || definition.trim().length() == 0) {
+        continue;
+      }
+      PatternHandler patternHandler = new PatternHandler(true);      
+      try {
+        PatternData patternData = patternHandler.load(definition);
+        if (patternData != null) {
+          if (DEBUG) {
+            EGFConsolePlugin.getConsole().logWarning(
+              NLS.bind(
+                "Factory Component Should be updated ''{0}''", //$NON-NLS-1$ 
+                patternData.getFactoryComponentId()
+              )
+            );
+          }                  
+        }
+      } catch (Throwable t) {
+        if (DEBUG) {
+          EGFConsolePlugin.getConsole().logThrowable(
+            NLS.bind(
+              "Unable to load Pattern Model ''{0}''", //$NON-NLS-1$ 
+              definition
+            ), 
+            t
+          );
+        }
+        PatternActivator.getDefault().log(t);
+        continue;
+      }          
+    }    
+  }
+  
+  protected void rebuildPatternModel(Collection<IDescriptor> descriptors_p) {
+    if (descriptors_p == null) {
+      return;
+    }
+    for (IDescriptor descriptor : descriptors_p) {
+      String definition = (String) descriptor.getValue(IPatternConstants.PATTERN_MODEL_ATTRIBUTE_NAME);
+      if (definition == null || definition.trim().length() == 0) {
+        continue;
+      }
+      PatternHandler patternHandler = new PatternHandler(true);      
+      try {
+        PatternData patternData = patternHandler.load(definition);
+        if (patternData != null) {
+          if (DEBUG) {
+            EGFConsolePlugin.getConsole().logWarning(
+              NLS.bind(
+                "Pattern Model Should be updated ''{0}''", //$NON-NLS-1$ 
+                definition
+              )
+            );
+          }                  
+        }
+      } catch (Throwable t) {
+        if (DEBUG) {
+          EGFConsolePlugin.getConsole().logThrowable(
+            NLS.bind(
+              "Unable to load Pattern Model ''{0}''", //$NON-NLS-1$ 
+              definition
+            ), 
+            t
+          );
+        }
+        PatternActivator.getDefault().log(t);
+        continue;
+      }            
+    }    
+  }  
+        
+  private void cleanup() {
+    _patterns = null;
+  }  
+
+  /* (non-Javadoc)
+   * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
+   */
+  protected void clean(IProgressMonitor monitor_p) throws CoreException {
+    // Nothing to do
+  }
+  
+  private boolean initialize(IProgressMonitor monitor_p) throws CoreException {
+    // Check    
+    if (PatternActivator.getDefault().getBundle().getState() != Bundle.ACTIVE || monitor_p.isCanceled()) {
+      return false;
+    }
+    // Get the current Project
+    IProject project = getProject();
+    // At this stage we check unknown, binary or non java project
+    if (project == null || project.isAccessible() == false || project.hasNature(JavaCore.NATURE_ID) == false) {
+      return false;
+    }
+    // Store the current JavaProject
+    _javaProject = JavaCore.create(project);
+    return true;
+  }
+  
+  protected Map<String, IDescriptor> getPatterns() {
+    if (_patterns == null) {
+      _patterns = PatternRegistry.getPatterns(_javaProject.getProject());
+    }
+    return _patterns;
+  }
+            
+}
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/builders/PatternTemplateBuilder.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/builders/PatternTemplateBuilder.java
new file mode 100644
index 0000000..6248239
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/builders/PatternTemplateBuilder.java
@@ -0,0 +1,363 @@
+/**
+ * <copyright>
+ *
+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ *
+ *  Contributors:
+ *      Thales Corporate Services S.A.S - Initial API and implementation
+ *      Soyatec - Contribution
+ *
+ * </copyright>
+ * 
+ */
+
+package org.eclipse.egf.pattern.internal.builders;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.osgi.util.NLS;
+
+import org.eclipse.egf.common.constant.IPatternConstants;
+import org.eclipse.egf.common.descriptor.IDescriptor;
+import org.eclipse.egf.common.helper.ExtensionPointHelper;
+import org.eclipse.egf.common.helper.MathHelper;
+import org.eclipse.egf.console.EGFConsolePlugin;
+import org.eclipse.egf.pattern.PatternActivator;
+import org.eclipse.egf.pattern.ecore.PatternConstants;
+import org.eclipse.egf.pattern.ecore.PatternHandler;
+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;
+import org.eclipse.egf.pattern.internal.PatternRegistry;
+import org.eclipse.egf.pattern.internal.PatternTemplateRegistry;
+import org.eclipse.egf.pattern.production.GeneratedContentHelper;
+import org.eclipse.egf.pattern.production.PatternTemplateProducer;
+
+
+public class PatternTemplateBuilder extends IncrementalProjectBuilder {
+  
+  private static boolean DEBUG = PatternActivator.getDefault().isDebugging();
+  
+  private static IProject[] EMPTY_LIST = new IProject [0];
+
+  private BinaryGeneratedPatternFolderVisitor _patternVisitor = new BinaryGeneratedPatternFolderVisitor();
+      
+  private IPath _binaryOutputPatternPath;
+  
+  private IJavaProject _javaProject;
+    
+  private Map<String, IDescriptor> _patterns;
+  
+  private Map<String, IDescriptor> _patternTemplates;  
+
+  class BinaryGeneratedPatternFolderVisitor implements IResourceDeltaVisitor {
+    
+    private Collection<IDescriptor> _generate = new ArrayList<IDescriptor>();
+        
+    private Collection<IDescriptor> _clean = new ArrayList<IDescriptor>();    
+
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			if (delta != null) {
+				int kind = delta.getKind();
+				IResource resource = delta.getResource();
+				// Process Folders who contain Pattern model generated classes
+				if (resource.getType() == IResource.FOLDER) {
+					if (_binaryOutputPatternPath.toString().startsWith(resource.getFullPath().toString())) {
+						// Parent folder, Deeper analysis
+						return true;
+					} else if (_binaryOutputPatternPath.equals(resource.getFullPath())) {
+						// Root folder of pattern model generated classes
+						// Everything has been deleted
+						if (kind == IResourceDelta.REMOVED) {
+							// Clean all existing pattern templates
+							_clean.addAll(getPatternTemplates().values());
+							// Stop deeper analysis
+							return false;
+						}
+						// Deeper analysis
+						return true;
+					} else if (resource.getFullPath().toString().startsWith(_binaryOutputPatternPath.toString())) {
+						// Inner pattern model generated classes folder
+						// Pattern Folder has been removed
+						if (kind == IResourceDelta.REMOVED) {
+							// check if we have an existing pattern template
+							// descriptor
+							IDescriptor patternTemplateDescriptor = getPatternTemplate((IFolder) resource);
+							if (patternTemplateDescriptor == null) {
+								// Nothing to process, Stop deeper analysis
+								return false;
+							}
+							_clean.add(patternTemplateDescriptor);
+						}
+						// Pattern Folder has been added or changed descriptor
+						if (kind == IResourceDelta.ADDED || kind == IResourceDelta.CHANGED) {
+							// check if we have an existing pattern
+							IDescriptor patternDescriptor = getPattern((IFolder) resource);
+							if (patternDescriptor == null) {
+								// Nothing to process, Stop deeper analysis
+								return false;
+							}
+							_generate.add(patternDescriptor);
+						}
+						// Stop deeper analysis
+						return false;
+					}
+				} else if (resource.getType() == IResource.PROJECT) {
+					// Project, Deep analysis
+					return true;
+				} else if (resource.getType() == IResource.FILE) {
+					String fileExtension = resource.getFileExtension();
+					if ( fileExtension == null || "".equals(fileExtension) || !PatternConstants.PATTERN_METHOD_FILE_EXTENSION.equals(fileExtension) || !(resource.getParent() instanceof IFolder))
+						return false;
+					IDescriptor patternDescriptor = getPattern((IFolder) resource.getParent());
+					if (patternDescriptor == null) 
+						return false;
+					_generate.add(patternDescriptor);
+				}
+			}
+			return true;
+		}
+
+    public void reset() {
+      _generate.clear();      
+      _clean.clear();      
+    }
+
+    public Collection<IDescriptor> getGenerate() {
+      return _generate;
+    }
+    
+    public Collection<IDescriptor> getClean() {
+      return _clean;
+    }    
+
+  }
+
+  @SuppressWarnings("unchecked")
+  protected IProject[] build(int kind_p, Map args_p, IProgressMonitor monitor_p) throws CoreException {
+    // Initialize   
+    if (initialize(monitor_p) == false) {
+      return EMPTY_LIST;
+    }
+    // Let's build our delta
+    try {
+      IResourceDelta delta = getDelta(_javaProject.getProject());    
+      if (kind_p != FULL_BUILD || delta != null) {
+        if (delta.getKind() != IResourceDelta.NO_CHANGE) {
+          // Visit delta
+          _patternVisitor.reset();
+          delta.accept(_patternVisitor);
+          // Clean
+          clean(_patternVisitor.getClean());
+          // Generate
+          generate(_patternVisitor.getGenerate(), monitor_p);          
+        }
+      } else {
+        // Generate All available patterns
+        generate(getPatterns().values(), monitor_p);        
+      }
+    } finally {
+      cleanup();
+    }
+    // Nothing to return yet
+    return EMPTY_LIST;
+  }
+      
+  protected void generate(Collection<IDescriptor> descriptors_p, IProgressMonitor monitor_p) {
+    if (descriptors_p == null) {
+      return;
+    }
+    // Debug Stuff
+    int rank = 1;
+    long start = System.currentTimeMillis();
+    long stepStart = start;
+    // Generate
+    for (IDescriptor descriptor : descriptors_p) {
+      String definition = (String) descriptor.getValue(IPatternConstants.PATTERN_MODEL_ATTRIBUTE_NAME);
+      if (definition == null || definition.trim().length() == 0) {
+        continue;
+      }
+      PatternHandler patternHandler = new PatternHandler(true);
+      try {        
+        PatternData patternData = patternHandler.load(definition);
+        if (patternData != null) {                  
+          PatternTemplateProducer.generateTemplate(patternData);          
+          if (DEBUG) {
+            long stepStop = System.currentTimeMillis();            
+            EGFConsolePlugin.getConsole().logInfo(
+              NLS.bind(
+                "Generate Pattern Template ''{0}'', step {1}/{2}", //$NON-NLS-1$ 
+                new Object[] {
+                  definition,
+                  rank++,
+                  descriptors_p.size()
+                }
+              )
+            );
+            EGFConsolePlugin.getConsole().logWarning(
+              NLS.bind(
+                "Total elapsed {0}, Step elapsed {1}", //$NON-NLS-1$ 
+                MathHelper.formatAsDuration(stepStop - start),                  
+                MathHelper.formatAsDuration(stepStop - stepStart)
+              ),
+              1
+            );            
+            stepStart = System.currentTimeMillis();            
+          }             
+        }
+      } catch (Throwable t) {
+        if (DEBUG) {
+          EGFConsolePlugin.getConsole().logThrowable(
+            NLS.bind(
+              "Unable to load Pattern Model ''{0}''", //$NON-NLS-1$ 
+              definition
+            ), 
+            t
+          );
+        }
+        PatternActivator.getDefault().log(t);
+        continue;
+      } finally {
+        // Check Monitor
+        if (monitor_p.isCanceled()) {
+          break;
+        }
+      }
+    }
+    // Refresh project.
+    try {
+      _javaProject.getProject().refreshLocal(IResource.DEPTH_INFINITE, monitor_p);
+    } catch (CoreException ce) {
+      PatternActivator.getDefault().log(ce);
+      if (DEBUG) {
+        EGFConsolePlugin.getConsole().logThrowable(
+          NLS.bind(
+            "Unable to refresh project ''{0}''", //$NON-NLS-1$
+            _javaProject.getProject().getName()
+          ),
+          ce
+        );
+      }
+    }
+  }  
+  
+  protected void clean(Collection<IDescriptor> descriptors_p) {
+    if (descriptors_p == null) {
+      return;
+    }
+    for (IDescriptor descriptor : descriptors_p) {
+      String id = (String) descriptor.getValue(ExtensionPointHelper.ATT_ID);
+      if (id == null || id.trim().length() == 0) {
+        continue;
+      }
+      if (DEBUG) {
+        EGFConsolePlugin.getConsole().logInfo(
+          NLS.bind(
+            "Clean Pattern Template ''{0}''", //$NON-NLS-1$ 
+            id
+          )
+        ); 
+      }         
+      PatternTemplateProducer.cleanGeneratedStructures(_javaProject, descriptor);               
+    }    
+  }
+        
+  private void cleanup() {
+    _patterns = null;
+    _patternTemplates = null;
+  }  
+
+  /* (non-Javadoc)
+   * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
+   */
+  protected void clean(IProgressMonitor monitor_p) throws CoreException {
+    // Initialize   
+    if (initialize(monitor_p) == false) {
+      return;
+    }
+    // Let's do our clean job
+    try {
+      // Clean all available pattern templates
+      clean(getPatternTemplates().values()); 
+    } finally {
+      cleanup();
+    }    
+  }
+  
+  private boolean initialize(IProgressMonitor monitor_p) throws CoreException {
+    // Check    
+    if (PatternActivator.getDefault().getBundle().getState() != Bundle.ACTIVE || monitor_p.isCanceled()) {
+      return false;
+    }
+    // Get the current Project
+    IProject project = getProject();
+    // At this stage we check unknown, binary or non java project
+    if (project == null || project.isAccessible() == false || project.hasNature(JavaCore.NATURE_ID) == false) {
+      return false;
+    }
+    // Store the current JavaProject
+    _javaProject = JavaCore.create(project);
+    // Get the generated output bin pattern folder
+    _binaryOutputPatternPath = GeneratedContentHelper.getBinaryOutputPatternGeneratedFolder(_javaProject);
+    if (_binaryOutputPatternPath == null) {
+      return false;
+    }
+    return true;
+  }
+  
+  protected Map<String, IDescriptor> getPatterns() {
+    if (_patterns == null) {
+      _patterns = PatternRegistry.getPatterns(_javaProject.getProject());
+    }
+    return _patterns;
+  }
+  
+  protected Map<String, IDescriptor> getPatternTemplates() {
+    if (_patternTemplates == null) {
+      _patternTemplates = PatternTemplateRegistry.getPatternTemplates(_javaProject.getProject());
+    }
+    return _patternTemplates;
+  }  
+    
+  protected IDescriptor getPattern(IFolder folder_p) {
+    if (folder_p == null) {
+      return null;
+    }
+    // Build a possible pattern shortID
+    String shortID = GeneratedContentHelper.getPatternIdentifier(folder_p);
+    if (shortID == null) {
+      return null;
+    }
+    return getPatterns().get(shortID);
+  }
+    
+  protected IDescriptor getPatternTemplate(IFolder folder_p) {
+    if (folder_p == null) {
+      return null;
+    }
+    // Build a possible pattern shortID
+    String shortID = GeneratedContentHelper.getPatternIdentifier(folder_p);
+    if (shortID == null) {
+      return null;
+    }
+    return getPatternTemplates().get(shortID);
+  }  
+  
+}
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/production/jet/JetProductionContributor.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/production/jet/JetProductionContributor.java
new file mode 100644
index 0000000..8b2b21f
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/internal/production/jet/JetProductionContributor.java
@@ -0,0 +1,727 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.internal.production.jet;

+

+import java.io.ByteArrayOutputStream;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+

+import org.eclipse.core.runtime.Path;

+

+import org.eclipse.emf.codegen.jet.JETCompiler;

+import org.eclipse.emf.codegen.jet.JETException;

+import org.eclipse.emf.codegen.jet.JETMark;

+import org.eclipse.emf.codegen.jet.JETSkeleton;

+import org.eclipse.emf.common.util.URI;

+import org.eclipse.emf.ecore.EObject;

+import org.eclipse.emf.ecore.EOperation;

+import org.eclipse.emf.ecore.EPackage;

+import org.eclipse.emf.ecore.resource.Resource;

+import org.eclipse.emf.query.conditions.eobjects.EObjectTypeRelationCondition;

+import org.eclipse.emf.query.conditions.eobjects.TypeRelation;

+import org.eclipse.emf.query.statements.FROM;

+import org.eclipse.emf.query.statements.SELECT;

+import org.eclipse.emf.query.statements.WHERE;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.constant.IPatternConstants;

+import org.eclipse.egf.common.helper.EcoreHelper;

+import org.eclipse.egf.common.helper.ExtensionPointHelper;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.StringHelper;

+import org.eclipse.egf.common.misc.Couple;

+import org.eclipse.egf.core.context.ProductionContext;

+import org.eclipse.egf.pattern.PatternActivator;

+import org.eclipse.egf.pattern.ecore.AnnotationHandler;

+import org.eclipse.egf.pattern.ecore.PatternConditionHelper;

+import org.eclipse.egf.pattern.ecore.PatternConstants;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pattern.ecore.condition.IConditionConstants;

+import org.eclipse.egf.pattern.ecore.condition.IPatternCondition;

+import org.eclipse.egf.pattern.execution.IPatternExecutionReporter;

+import org.eclipse.egf.pattern.execution.PatternExecutionHelper;

+import org.eclipse.egf.pattern.production.IProductionContributor;

+import org.eclipse.egf.pattern.production.TemplateType;

+import org.eclipse.egf.pattern.production.jet.JETConstants;

+import org.eclipse.egf.pattern.production.template.TemplateHelper;

+import org.eclipse.egf.pattern.relations.ParameterRelation;

+import org.eclipse.egf.pde.EgfPdeActivator;

+import org.eclipse.egf.pde.pattern.plugin.command.PatternTemplateExtensionFactory;

+import org.eclipse.egf.pde.plugin.command.IPluginChangesCommand;

+import org.eclipse.egf.pde.plugin.command.IPluginChangesCommandRunner;

+import org.eclipse.egf.pde.plugin.manifest.command.ManifestChangeCommandFactory;

+

+

+/**

+ * @author Guillaume Brocard

+ */

+public class JetProductionContributor implements IProductionContributor {

+  

+  /**

+   * Generated template Java class default name suffix.

+   */

+  private static final String JET_SKELETON_CLASS_DEFAULT_SUFFIX = "Generator"; //$NON-NLS-1$

+  

+  /**

+   * Jet skeleton 'imports' declaration.

+   */

+  private static final String JET_SKELETON_IMPORTS_DECLARATION = " imports="; //$NON-NLS-1$

+  

+  /**

+   * Jet skeleton 'class' declaration.

+   */

+  private static final String JET_SKELETON_CLASS_DECLARATION = " class="; //$NON-NLS-1$

+  

+  /**

+   * Jet skeleton 'package' declaration.

+   */

+  private static final String JET_SKELETON_PACKAGE_DECLARATION = " package="; //$NON-NLS-1$

+  

+  /**

+   * Jet skeleton start mark-up.

+   */

+  private static final String JET_SKELETON_JSP_START = JETConstants.JET_MARKUP_START + "@ jet"; //$NON-NLS-1$

+  

+  /**

+   * Jet generated template skeleton key for compiler options map.

+   */

+  private static final String JET_GENERATED_TEMPLATE_SKELETON_KEY = "skeleton"; //$NON-NLS-1$

+  

+  /**

+   * Jet generated template skeleton path.

+   */

+  private static final String JET_GENERATED_TEMPLATE_SKELETON_PATH = "/org.eclipse.egf.pattern/resources/templates/generator.skeleton"; //$NON-NLS-1$

+  

+  /**

+   * New initialized string builder (with string buffer).

+   */

+  private static final String NEW_INITIALIZED_STRING_BUILDER = " = new StringBuilder(stringBuffer);\n"; //$NON-NLS-1$

+  

+  /**

+   * Declare a string builder prefix directive.

+   */

+  private static final String DECLARE_STRING_BUILDER = "StringBuilder "; //$NON-NLS-1$

+  

+  /**

+   * Clear JET string buffer.

+   */

+  private static final String CLEAR_STRING_BUFFER = "stringBuffer = new StringBuffer();\n"; //$NON-NLS-1$

+  

+  /**

+   * Call to new, with a space suffix.

+   */

+  private static final String NEW_CALL = "new "; //$NON-NLS-1$

+  

+  /**

+   * Close java generic type usage.

+   */

+  private static final String CLOSE_JAVA_1_5_GENERIC_TYPE_USAGE = "> "; //$NON-NLS-1$

+  

+  /**

+   * Assignment directive.

+   */

+  private static final String ASSIGNMENT_DIRECTIVE = " = "; //$NON-NLS-1$

+  

+  /**

+   * Close method call, then new line.

+   */

+  private static final String JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE = ");\n"; //$NON-NLS-1$

+  

+  /**

+   * Start a new block.

+   */

+  private static final String JAVA_CODE_OPEN_BLOCK = "{\n"; //$NON-NLS-1$

+  

+  /**

+   * Close parenthesis, then start a new block.

+   */

+  private static final String JAVA_CODE_CLOSE_PAREN_AND_OPEN_BLOCK =

+      ICommonConstants.EMPTY_STRING 

+    + ICommonConstants.PARENTHESIS_CLOSE_CHARACTER

+    + ICommonConstants.WHITE_SPACE_CHARACTER + JAVA_CODE_OPEN_BLOCK;

+  

+  /**

+   * Close block java code.

+   */

+  private static final String JAVA_CODE_CLOSE_BLOCK = "}\n"; //$NON-NLS-1$

+  

+  /**

+   * Jet java code end.

+   */

+  private static final String JAVA_CODE_END = "%>\n"; //$NON-NLS-1$

+  

+  /**

+   * Jet java code start.

+   */

+  private static final String JAVA_CODE_BEGIN = "<%\n"; //$NON-NLS-1$

+  

+  /**

+   * Set condition context Java call.

+   */

+  private static final String SET_CONDITION_CONTEXT_CALL = ".setContext(context);\n"; //$NON-NLS-1$

+

+  /**

+   * @see org.eclipse.egf.pattern.production.IProductionContributor#createPatternMatchingTemplates(org.eclipse.egf.pattern.ecore.PatternHandler.PatternData,

+   *      java.util.List)

+   */

+  public Couple<StringBuilder, StringBuilder> createPatternMatchingTemplates(PatternData patternData_p, List<ParameterRelation> parameters_p) {

+    String patternFullId = patternData_p.getPattern().getId();

+    // Replace both pre and post matching results at the same time.

+    StringBuilder preMatchingResult = new StringBuilder();

+    StringBuilder postMatchingResult = new StringBuilder();

+    // Should buffer delegation be used ?

+    boolean delegateBuffer = patternData_p.getProductionOptionsHandler().shouldModifyBuffer();

+    // Open java code.

+    preMatchingResult.append(JAVA_CODE_BEGIN);

+    postMatchingResult.append(JAVA_CODE_BEGIN);

+    // Create a new Java code block for variable names uniqueness.

+    if (delegateBuffer) {

+      preMatchingResult.append(JAVA_CODE_OPEN_BLOCK);

+    }

+    // Pattern name with first letter set to lower case.

+    String patternNameToLowerFirst = StringHelper.toLowerFirst(

+      StringHelper.replaceNonWordCharacters(

+        patternData_p.getPattern().getShortId(), 

+        null

+      )

+    );

+    // Add pattern starting comment tag.

+    preMatchingResult

+      .append("// Start of ") //$NON-NLS-1$

+      .append(patternData_p.getPatternLogicalName())

+      .append(" (full id = ") //$NON-NLS-1$

+      .append(patternFullId)

+      .append(").\n"); //$NON-NLS-1$

+    // Add this piece of code if buffer is to be delegated.

+    String pbVariableName = null;

+    String pbSaveVariableName = null;

+    if (delegateBuffer) {

+      // Replace string buffer with a pattern specific string builder.

+      // Pattern builder variable name.

+      pbVariableName = patternNameToLowerFirst + "Builder"; //$NON-NLS-1$

+      // Pattern builder save variable name.

+      pbSaveVariableName = pbVariableName + "Save"; //$NON-NLS-1$

+      // Declare save builder and initialize it.

+      preMatchingResult

+        .append(DECLARE_STRING_BUILDER)

+        .append(pbSaveVariableName)

+        .append(NEW_INITIALIZED_STRING_BUILDER);

+    }

+    // Deals with parameters, if any.

+    if (parameters_p != null && parameters_p.isEmpty() == false) {

+      // Add this piece of code if buffer is to be delegated.

+      if (delegateBuffer) {

+        // Declare pattern builder and initialize it.

+        preMatchingResult

+          .append(DECLARE_STRING_BUILDER)

+          .append(pbVariableName)

+          .append(" = new StringBuilder();\n"); //$NON-NLS-1$

+      }

+      // EObject fully qualified name.

+      String eObjectFullyQualifiedName = EObject.class.getName();

+      // Pattern condition variable name.

+      String pcVariableName = patternNameToLowerFirst + IConditionConstants.CONDITION_CLASS_NAME_SUFFIX;

+      // Declare pattern condition class instance.

+      String patternConditionInterfaceName = IPatternCondition.class.getName();

+      preMatchingResult

+        .append(patternConditionInterfaceName)

+        .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+        .append(pcVariableName);

+      preMatchingResult.append(ASSIGNMENT_DIRECTIVE);

+      preMatchingResult

+        .append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER)

+        .append(patternConditionInterfaceName)

+        .append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER)

+        .append(ICommonConstants.WHITE_SPACE_CHARACTER);

+      preMatchingResult

+        .append(ExtensionPointHelper.class.getName())

+        .append(".createExecutableExtension("); //$NON-NLS-1$

+      preMatchingResult

+        .append(ICommonConstants.QUOTE_CHARACTER)

+        .append(PatternActivator.getDefault().getPluginID())

+        .append(ICommonConstants.QUOTE_CHARACTER);

+      preMatchingResult.append(",\"patternCondition\""); //$NON-NLS-1$

+      preMatchingResult.append(",\"patternId\""); //$NON-NLS-1$

+      preMatchingResult

+        .append(ICommonConstants.COMMA_CHARACTER)

+        .append(ICommonConstants.QUOTE_CHARACTER)

+        .append(patternFullId)

+        .append(ICommonConstants.QUOTE_CHARACTER);

+      preMatchingResult.append(JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE);

+      // Test it.

+      preMatchingResult

+        .append("if (null != ") //$NON-NLS-1$

+        .append(pcVariableName)

+        .append(JAVA_CODE_CLOSE_PAREN_AND_OPEN_BLOCK);

+      // If it's not being null, then create all query statements for the parameters.

+      // First set context to the condition class.

+      preMatchingResult

+        .append(pcVariableName)

+        .append(SET_CONDITION_CONTEXT_CALL);

+      // Parameters list is not tested against nullity or emptiness.

+      // It is expected that the pattern content has not changed between the generation of the condition structures and the

+      // use of the pattern. If not, there has been an error during a modification (such as a re-factoring).

+      String patternParametersVariableName = patternNameToLowerFirst + "Parameters"; //$NON-NLS-1$

+      preMatchingResult

+        .append(List.class.getName())

+        .append('<')

+        .append(ParameterRelation.class.getName())

+        .append(CLOSE_JAVA_1_5_GENERIC_TYPE_USAGE);

+      preMatchingResult.append(patternParametersVariableName);

+      preMatchingResult

+        .append(ASSIGNMENT_DIRECTIVE)

+        .append(PatternConditionHelper.class.getName())

+        .append(".getPatternParameters("); //$NON-NLS-1$

+      preMatchingResult

+        .append(ICommonConstants.QUOTE_CHARACTER)

+        .append(patternFullId)

+        .append(ICommonConstants.QUOTE_CHARACTER);

+      preMatchingResult.append(JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE);

+      // Define the tuple map result.

+      String resultMapVariableName = patternNameToLowerFirst + "Result"; //$NON-NLS-1$

+      String resultMapVariableGenerics = "<String, " + eObjectFullyQualifiedName + CLOSE_JAVA_1_5_GENERIC_TYPE_USAGE; //$NON-NLS-1$

+      preMatchingResult

+        .append(Map.class.getName())

+        .append(resultMapVariableGenerics);

+      preMatchingResult

+        .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+        .append(resultMapVariableName)

+        .append(ASSIGNMENT_DIRECTIVE);

+      preMatchingResult

+        .append(NEW_CALL)

+        .append(HashMap.class.getName())

+        .append(resultMapVariableGenerics)

+        .append("();\n"); //$NON-NLS-1$

+      // Injected in preMatchingResult in the end. Allows to cycle through parameters only one time.

+      StringBuilder temporaryLoops = new StringBuilder();

+      StringBuilder temporaryCondition = new StringBuilder("if (") //$NON-NLS-1$

+        .append(pcVariableName)

+        .append(".check("); //$NON-NLS-1$

+      // Injected in postMatchingResult in the end, for the very same reason.

+      StringBuilder temporaryPostLoops = new StringBuilder();

+      // Create string content based on given parameters.

+      int i = 0;

+      for (Iterator<ParameterRelation> parameters = parameters_p.iterator(); parameters.hasNext();) {

+        ParameterRelation currentParameter = parameters.next();

+        // Parameter name.

+        String paramName = currentParameter.getName();

+        // Parameter type name.

+        String paramTypeName = currentParameter.getType().getName();

+        // Parameter relation variable.

+        String paramRelationName = paramName + "Relation"; //$NON-NLS-1$

+        preMatchingResult

+          .append(ParameterRelation.class.getName())

+          .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+          .append(paramRelationName);

+        preMatchingResult

+          .append(ASSIGNMENT_DIRECTIVE)

+          .append(patternParametersVariableName)

+          .append(".get(") //$NON-NLS-1$

+          .append(i)

+          .append(JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE);

+        // Loop parameter name.

+        String loopParamName = paramName + "Loop"; //$NON-NLS-1$

+        // Declared collection of objects for current parameter.

+        String collectionVariableName = paramName + "Collection"; //$NON-NLS-1$

+        // Compute such a collection.

+        preMatchingResult

+          .append(Collection.class.getName())

+          .append('<')

+          .append(eObjectFullyQualifiedName)

+          .append(CLOSE_JAVA_1_5_GENERIC_TYPE_USAGE)

+          .append(collectionVariableName)

+          .append(ASSIGNMENT_DIRECTIVE);

+        preMatchingResult

+          .append(NEW_CALL)

+          .append(SELECT.class.getName())

+          .append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+        preMatchingResult

+          .append(NEW_CALL)

+          .append(FROM.class.getName())

+          .append("(resource.getContents()), "); //$NON-NLS-1$

+        preMatchingResult

+          .append(NEW_CALL)

+          .append(WHERE.class.getName())

+          .append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+        preMatchingResult

+          .append(NEW_CALL)

+          .append(EObjectTypeRelationCondition.class.getName())

+          .append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+        preMatchingResult

+          .append(EcoreHelper.class.getName())

+          .append(".getStaticClass(") //$NON-NLS-1$

+          .append(paramRelationName)

+          .append(".getType()),"); //$NON-NLS-1$

+        // Append query relation type.

+        // By default, always search for elements of the same type, or that are a sub-type, of given one.

+        preMatchingResult

+          .append(TypeRelation.class.getName())

+          .append(".SAMETYPE_OR_SUBTYPE_LITERAL"); //$NON-NLS-1$

+        // Close query call.

+        preMatchingResult.append("))).execute();\n"); //$NON-NLS-1$

+        // Add for directive associated to current parameter.

+        temporaryLoops

+          .append("for (") //$NON-NLS-1$

+          .append(eObjectFullyQualifiedName)

+          .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+          .append(loopParamName).append(" : ") //$NON-NLS-1$

+          .append(collectionVariableName)

+          .append(JAVA_CODE_CLOSE_PAREN_AND_OPEN_BLOCK);

+        // Add real parameter declaration (for use in the template), for the parameter is used as an EObject so far.

+        // Eg : EClass myParameter = (EClass) myParameterLoop;

+        temporaryLoops

+          .append(paramTypeName)

+          .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+          .append(paramName);

+        temporaryLoops

+          .append(ASSIGNMENT_DIRECTIVE)

+          .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+          .append(ICommonConstants.PARENTHESIS_OPEN_CHARACTER);

+        temporaryLoops

+          .append(paramTypeName)

+          .append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER)

+          .append(ICommonConstants.WHITE_SPACE_CHARACTER);

+        temporaryLoops

+          .append(loopParamName)

+          .append(ICommonConstants.SEMICOLON_CHARACTER)

+          .append(ICommonConstants.EOL_CHARACTER);

+        // Add completion of the tuple to postMatchingResult.

+        postMatchingResult

+          .append(resultMapVariableName)

+          .append(".put(") //$NON-NLS-1$

+          .append(paramRelationName)

+          .append(".getName(), "); //$NON-NLS-1$

+        postMatchingResult

+          .append(loopParamName)

+          .append(JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE);

+        // Add an end for directive.

+        temporaryPostLoops.append(JAVA_CODE_CLOSE_BLOCK);

+        // Append parameter name for condition call.

+        temporaryCondition.append(loopParamName);

+        if (parameters.hasNext()) {

+          temporaryCondition.append(ICommonConstants.COMMA_CHARACTER);

+        }

+        // Increment parameter position.

+        i++;

+      }

+      // Add for loops to pre-matching.

+      preMatchingResult.append(temporaryLoops.toString());

+      // If condition directive.

+      preMatchingResult.append(temporaryCondition.toString());

+      preMatchingResult.append(")) {\n"); //$NON-NLS-1$

+      // Add this piece of code if buffer is to be delegated.

+      if (delegateBuffer) {

+        // Clear string buffer.

+        preMatchingResult.append(CLEAR_STRING_BUFFER);

+        // Call reporter for current string buffer content.

+        // Output result.

+        postMatchingResult

+          .append("reporter.patternLoopExecutionFinished(") //$NON-NLS-1$

+          .append("stringBuffer.toString(),"); //$NON-NLS-1$

+        // Pattern fullId.

+        postMatchingResult

+          .append(ICommonConstants.QUOTE_CHARACTER)

+          .append(patternFullId)

+          .append(ICommonConstants.QUOTE_CHARACTER)

+          .append(ICommonConstants.COMMA_CHARACTER);

+        // Context.

+        postMatchingResult.append("context,"); //$NON-NLS-1$

+        // Resulting tuple.

+        postMatchingResult

+          .append(resultMapVariableName)

+          .append(JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE);

+        // Append tuple result to pattern builder.

+        postMatchingResult

+          .append(pbVariableName)

+          .append(".append(stringBuffer)") //$NON-NLS-1$

+          .append(ICommonConstants.SEMICOLON_CHARACTER)

+          .append(ICommonConstants.EOL_CHARACTER);

+      }

+      // Append loops closures.

+      postMatchingResult.append(temporaryPostLoops);

+      // Close if condition directive.

+      postMatchingResult.append(JAVA_CODE_CLOSE_BLOCK);

+      // Close if condition not null directive.

+      postMatchingResult.append(JAVA_CODE_CLOSE_BLOCK);

+    } else if (delegateBuffer) {

+      // Clear string buffer, now that it is saved.

+      preMatchingResult.append(CLEAR_STRING_BUFFER);

+      // Set pattern builder to string buffer, when work is done.

+      postMatchingResult

+        .append(DECLARE_STRING_BUILDER)

+        .append(pbVariableName)

+        .append(NEW_INITIALIZED_STRING_BUILDER);

+    }

+    // Add this piece of code if buffer is to be delegated.

+    if (delegateBuffer) {

+      // Restore string buffer.

+      postMatchingResult

+        .append("stringBuffer = new StringBuffer(") //$NON-NLS-1$

+        .append(pbSaveVariableName)

+        .append(ICommonConstants.PARENTHESIS_CLOSE_CHARACTER);

+      postMatchingResult

+        .append(".append(") //$NON-NLS-1$

+        .append(pbVariableName)

+        .append(JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE);

+      // Call reporter for pattern execution.

+      postMatchingResult

+        .append("reporter.patternExecutionFinished(") //$NON-NLS-1$

+        .append(pbVariableName)

+        .append(".toString(),"); //$NON-NLS-1$

+      postMatchingResult

+        .append(ICommonConstants.QUOTE_CHARACTER)

+        .append(patternFullId)

+        .append(ICommonConstants.QUOTE_CHARACTER)

+        .append(ICommonConstants.COMMA_CHARACTER);

+      postMatchingResult

+        .append("context")

+        .append(JAVA_CODE_CLOSE_CALL_AND_RETURN_LINE); //$NON-NLS-1$

+    }

+    // Add pattern ending comment tag.

+    postMatchingResult

+      .append("// End of ") //$NON-NLS-1$

+      .append(patternData_p.getPatternLogicalName())

+      .append(" (full id = ") //$NON-NLS-1$

+      .append(patternData_p.getPattern().getId())

+      .append(").\n"); //$NON-NLS-1$

+    // Close Java code block for variable names uniqueness.

+    if (delegateBuffer) {

+      postMatchingResult.append(JAVA_CODE_CLOSE_BLOCK);

+    }

+    // Close java code.

+    preMatchingResult.append(JAVA_CODE_END);

+    postMatchingResult.append(JAVA_CODE_END);

+    // Return result.

+    return new Couple<StringBuilder, StringBuilder>(preMatchingResult, postMatchingResult);

+  }

+

+  /**

+   * @see org.eclipse.egf.pattern.production.IProductionContributor#compileTemplate(java.lang.String,

+   *      org.eclipse.egf.pattern.ecore.PatternHandler.PatternData)

+   */

+  public boolean compileTemplate(String patternTemplatePath_p, PatternData patternData_p) throws Exception {

+    // Now that the template is created, compile it.

+    // Get mandatory templates containers.

+    String[] templateContainerUris = { 

+      FileHelper.getFileFullUri(patternData_p.getPluginId() + TemplateHelper.TEMPLATES_ROOT_PATH).toString(),

+      URI.createURI("platform:/plugin/org.eclipse.emf.codegen.ecore/templates").toString() //$NON-NLS-1$ 

+    };

+    // Format template relative path.

+    String relativePath = new Path(patternTemplatePath_p).removeFirstSegments(2).toString();

+    // Call jet compiler.

+    JETCompiler jetCompiler = new JETCompiler(templateContainerUris, relativePath) {

+      @Override

+      public void handleDirective(String directive_p, JETMark start_p, JETMark stop_p, Map<String, String> attributes_p) throws JETException {

+        attributes_p.put(

+          JET_GENERATED_TEMPLATE_SKELETON_KEY, 

+          FileHelper.getFileFullUri(JET_GENERATED_TEMPLATE_SKELETON_PATH).toString()

+        );

+        super.handleDirective(directive_p, start_p, stop_p, attributes_p);

+      }

+    };

+    jetCompiler.parse();

+    // And write the resulting java code !

+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

+    jetCompiler.generate(outputStream);

+    JETSkeleton skeleton = jetCompiler.getSkeleton();

+    StringBuilder ultimateGeneratedClassPath = new StringBuilder(patternData_p.getJavaProject().getProject().getFolder(PatternConstants.GENERATION_SOURCE_FOLDER).getFullPath().toString());

+    ultimateGeneratedClassPath

+      .append(ICommonConstants.SLASH_CHARACTER)

+      .append(FileHelper.convertPackageNameToFolderPath(skeleton.getPackageName()));

+    ultimateGeneratedClassPath

+      .append(ICommonConstants.SLASH_CHARACTER)

+      .append(skeleton.getClassName())

+      .append(ICommonConstants.DOT_CHARACTER)

+      .append(IPatternConstants.JAVA_SOURCE_FILE_EXTENSION);

+    // Generated Java code.

+    String javaCode = new String(outputStream.toByteArray());

+    // Modify generated Java code buffer declaration.

+    if (patternData_p.getProductionOptionsHandler().shouldModifyBuffer()) {

+      StringBuilder codeTweak = new StringBuilder("StringBuffer stringBuffer = new StringBuffer();\n"); //$NON-NLS-1$

+      String helperClassName = PatternExecutionHelper.class.getName();

+      // Append resource variable.

+      codeTweak

+        .append(Resource.class.getName())

+        .append(" resource = ") //$NON-NLS-1$

+        .append(helperClassName)

+        .append(".getResource(argument);\n"); //$NON-NLS-1$

+      // Append context variable.

+      codeTweak

+        .append(ProductionContext.class.getName())

+        .append(" context = ") //$NON-NLS-1$

+        .append(helperClassName)

+        .append(".getContext(argument);\n"); //$NON-NLS-1$

+      // Append reporter variable.

+      codeTweak

+        .append(IPatternExecutionReporter.class.getName())

+        .append(" reporter = ") //$NON-NLS-1$

+        .append(helperClassName)

+        .append(".getExecutionReporter(argument);\n"); //$NON-NLS-1$

+      // Remove final statement in the declaration of the string buffer.

+      javaCode = javaCode.replace("final StringBuffer stringBuffer = new StringBuffer();", codeTweak.toString()); //$NON-NLS-1$

+    }

+    boolean fileWritten = FileHelper.writeFile(

+      ultimateGeneratedClassPath.toString(), 

+      true, 

+      javaCode

+    );

+    if (fileWritten) {

+      // Add containing package to exported ones.

+      performManifestChanges(

+        patternData_p, 

+        ManifestChangeCommandFactory.setExportedPackages(

+          new String[] { 

+            skeleton.getPackageName() 

+          }

+        )

+      );

+      // Update plugin.xml content accordingly.

+      performPluginChanges(

+        patternData_p, 

+        PatternTemplateExtensionFactory.setPatternTemplateExtension(

+          patternData_p.getPattern().getId(), 

+          new StringBuilder(skeleton.getPackageName())

+            .append(ICommonConstants.DOT_CHARACTER)

+            .append(skeleton.getClassName())

+            .toString(), 

+          TemplateType.JET.getId(),

+          patternTemplatePath_p

+        )

+      );

+    }

+    return fileWritten;

+  }

+

+  /**

+   * @see org.eclipse.egf.pattern.production.IProductionContributor#fillGenerateHeader(org.eclipse.egf.pattern.ecore.PatternHandler.PatternData,

+   *      org.eclipse.egf.pattern.ecore.AnnotationHandler)

+   */

+  public void fillGenerateHeader(PatternData patternData_p, AnnotationHandler handler_p) throws Exception {

+    // Precondition.

+    // Pattern is not expected to be compiled to a Java class.

+    // Do not create a useless header, that may well indeed be a new source of confusion for both users

+    // and Jet compiler.

+    if (patternData_p.getProductionOptionsHandler().shouldCompileTemplate() == false) {

+      return;

+    }

+    AnnotationHandler handler = handler_p;

+    // Instantiate annotation handler, if none provided.

+    if (handler == null) {

+      handler = new AnnotationHandler();

+    }

+    // Get template file path.

+    // First get generateHeader method.

+    // Should always be not null, for it is added automatically at creation time.

+    EOperation generateHeader = null;

+    String generateHeaderName = PatternConstants.GENERATE_HEADER_METHOD_NAME;

+    for (EOperation operation : patternData_p.getPattern().getEOperations()) {

+      if (generateHeaderName.equals(operation.getName())) {

+        generateHeader = operation;

+        break;

+      }

+    }

+    // Again, should not be null, for it is computed at creation time.

+    String generateHeaderUid = handler.getUid(generateHeader);

+    // Associated template file relative path.

+    String templateFileRelativePath = TemplateHelper.getTemplateRelativePath(

+        patternData_p.getPattern().getShortId(), 

+        patternData_p.getPluginId(),

+        generateHeaderName, 

+        generateHeaderUid

+    );

+    // Read generate header template content.

+    String generateHeaderContent = FileHelper.readFile(templateFileRelativePath);

+    // Existing content, stop here.

+    if (ICommonConstants.EMPTY_STRING.equals(StringHelper.replaceNonWordCharacters(generateHeaderContent, null).trim()) == false) {

+      return;

+    }

+    // Empty content, create default one.

+    // Start JET mark-up.

+    StringBuilder content = new StringBuilder(JET_SKELETON_JSP_START);

+    // Fill package structure and value.

+    content

+      .append(JET_SKELETON_PACKAGE_DECLARATION)

+      .append(ICommonConstants.QUOTE_CHARACTER);

+    // Computed package name

+    String patternName = patternData_p.getPatternLogicalName();

+    content

+      .append(patternData_p.getPluginId())

+      .append(ICommonConstants.DOT_CHARACTER)

+      .append(patternName.toLowerCase());

+    // End package structure.

+    content.append(ICommonConstants.QUOTE_CHARACTER);

+    // Fill class structure and value.

+    content

+      .append(JET_SKELETON_CLASS_DECLARATION)

+      .append(ICommonConstants.QUOTE_CHARACTER);

+    // Computed class name looks like toUpperFirst('patternName')Generator

+    content

+      .append(StringHelper.toUpperFirst(patternName))

+      .append(JET_SKELETON_CLASS_DEFAULT_SUFFIX);

+    // End class structure.

+    content.append(ICommonConstants.QUOTE_CHARACTER);

+    // Fill imports structure and value.

+    content

+      .append(JET_SKELETON_IMPORTS_DECLARATION)

+      .append(ICommonConstants.QUOTE_CHARACTER);

+    // Compute parameters dependencies.

+    List<ParameterRelation> parameters = patternData_p.getAllParameters();

+    // Add imports for each of them.

+    for (ParameterRelation parameterRelation : parameters) {

+      EPackage parameterPackage = parameterRelation.getType().getEPackage();

+      // Parameter package name.

+      String packageImportedName = EcoreHelper.getImportedPackageName(parameterPackage);

+      if (packageImportedName != null) {

+        // Added import looks like

+        content

+          .append(packageImportedName)

+          .append(ICommonConstants.DOT_CHARACTER)

+          .append(parameterRelation.getType().getName())

+          .append(ICommonConstants.WHITE_SPACE_CHARACTER);

+      }

+    }

+    // End imports structure.

+    content.append(ICommonConstants.QUOTE_CHARACTER);

+    // End JET mark-up.

+    content

+      .append(ICommonConstants.WHITE_SPACE_CHARACTER)

+      .append(JETConstants.JET_MARKUP_END)

+      .append(ICommonConstants.EOL_CHARACTER)

+      .append(ICommonConstants.EOL_CHARACTER);

+    // Write content to file.

+    FileHelper.writeFile(templateFileRelativePath, true, content.toString());

+  }

+

+  /**

+   * Perform changes on manifest file.

+   * @param patternData_p

+   * @param command_p

+   */

+  protected static void performManifestChanges(PatternData patternData_p, IPluginChangesCommand command_p) {

+    IPluginChangesCommandRunner runner = EgfPdeActivator.getDefault().getPluginChangesCommandRunner();

+    runner.performChangesOnManifest(patternData_p.getPluginId(), Collections.singletonList(command_p));

+  }

+

+  /**

+   * Perform changes on plugin.xml file.

+   * @param patternData_p

+   * @param command_p

+   */

+  protected static void performPluginChanges(PatternData patternData_p, IPluginChangesCommand command_p) {

+    IPluginChangesCommandRunner runner = EgfPdeActivator.getDefault().getPluginChangesCommandRunner();

+    runner.performChangesOnPlugin(patternData_p.getPluginId(), Collections.singletonList(command_p));

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/GeneratedContentHelper.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/GeneratedContentHelper.java
new file mode 100644
index 0000000..ce53930
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/GeneratedContentHelper.java
@@ -0,0 +1,288 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.production;

+

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.List;

+

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IFolder;

+import org.eclipse.core.resources.IProject;

+import org.eclipse.core.resources.IResource;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.jdt.core.IJavaProject;

+import org.eclipse.jdt.core.JavaModelException;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.constant.IPatternConstants;

+import org.eclipse.egf.common.constant.IPatternTemplateConstants;

+import org.eclipse.egf.common.descriptor.IDescriptor;

+import org.eclipse.egf.common.generator.IEgfGeneratorConstants;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.StringHelper;

+import org.eclipse.egf.common.misc.Couple;

+import org.eclipse.egf.pattern.Pattern;

+import org.eclipse.egf.pattern.ecore.PatternConstants;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pde.pattern.reader.WorkspacePatternTemplateExtensionReader;

+

+

+/**

+ * @author Guillaume Brocard

+ */

+public class GeneratedContentHelper {

+  

+  /**

+   * Get the pattern model output IFolder.

+   * @param project_p

+   * @return null if given parameter is null.

+   */

+  public static IFolder getPatternOutputPath(IProject project_p) {

+    // Precondition.

+    if (project_p == null) {

+      return null;

+    }  

+    IResource resource = project_p.findMember(PatternConstants.PATTERN_MODEL_FOLDER_IPATH);

+    if (resource != null && resource instanceof IFolder) {

+      return (IFolder) resource;

+    }

+    return null;

+  }    

+  

+  /**

+   * Get the binary output pattern generated IPath.

+   * @param project_p

+   * @return null if given parameter is null.

+   */

+  public static IPath getBinaryOutputPatternGeneratedFolder(IJavaProject project_p) {

+    // Precondition.

+    if (project_p == null) {

+      return null;

+    }  

+    IPath path = null;

+    try {

+      path = project_p.getOutputLocation()

+        .append( 

+          FileHelper.convertPackageNameToFolderPath(

+            PatternConstants.PATTERN_GENERATED_BASE_PACKAGE 

+          )

+      );

+    } catch (JavaModelException jme) {

+      // Just Ignore

+    }

+    return path;

+  }  

+  

+  /**

+   * Get an IFile as a normalized Pattern shortID.

+   * This implementation is the opposite transformation of

+   * the getPatternClassName method.

+   * @param pattern_p

+   * @return null if given parameter is null.

+   */

+  public static String getPatternIdentifier(IFile element_p) {

+    // Precondition.

+    if (element_p == null || element_p.getFullPath() == null) {

+      return null;

+    }        

+    return StringHelper.replaceNonWordCharactersWithDot(element_p.getFullPath().removeFileExtension().lastSegment());

+  }    

+    

+  /**

+   * Get pattern generated EMF class name.

+   * This implementation is the opposite transformation of

+   * the getPatternIdentifier method. 

+   * @param pattern_p

+   * @return null if given parameter is null.

+   */

+  public static String getPatternClassName(Pattern pattern_p) {

+    // Precondition.

+    if (pattern_p == null) {

+      return null;

+    }    

+    return StringHelper.replaceNonWordCharactersWithUnderscore(pattern_p.getShortId());

+  }

+  

+  /**

+   * Get an IFolder as a normalized Pattern shortID.

+   * This implementation is the opposite transformation of

+   * the getPatternPackageName method.  

+   * @param pattern_p

+   * @return null if given parameter is null.

+   */

+  public static String getPatternIdentifier(IFolder element_p) {

+    // Precondition.

+    if (element_p == null || element_p.getName() == null) {

+      return null;

+    }        

+    return StringHelper.replaceNonWordCharactersWithDot(StringHelper.toUpperFirst(element_p.getName()));

+  }  

+  

+  /**

+   * Get pattern generated EMF package name.

+   * This implementation is the opposite transformation of

+   * the getPatternIdentifier method.   

+   * @param pattern_p

+   * @return null if given parameter is null.

+   */

+  public static String getPatternPackageName(Pattern pattern_p) {

+    // Precondition.

+    if (pattern_p == null || pattern_p.getShortId() == null) {

+      return null;

+    }        

+    return StringHelper.replaceNonWordCharactersWithUnderscore(StringHelper.toLowerFirst(pattern_p.getShortId()));

+  }  

+  

+  /**

+   * Get pattern generated EMF package namespace prefix.

+   * @param pattern_p

+   * @return null if given parameter is null.

+   */

+  public static String getPatternPackageNsPrefix(Pattern pattern_p) {

+    return getPatternPackageName(pattern_p);

+  }    

+

+  /**

+   * Get pattern generated EMF package namespace URI.

+   * @param pattern_p

+   * @return null if given parameter is null.

+   */

+  public static String getPatternPackageNsURI(Pattern pattern_p) {

+    // Precondition.

+    if (pattern_p == null || pattern_p.getShortId() == null) {

+      return null;

+    }            

+    return PatternConstants.PATTERN_GENERATED_ECORE_NS_URI_PREFIX + pattern_p.getShortId();

+  }  

+  

+  /**

+   * Get pattern generated EMF root folder path.

+   * @param patternData_p

+   * @return null if given parameter is null.

+   */

+  public static String getEMFGeneratedRootFolderRelativePath(PatternData patternData_p) {

+    // Precondition.

+    if (patternData_p == null) {

+      return null;

+    }

+    // And its relative path.

+    IPath rootGeneratedPackageRelativePath = 

+      new Path(

+          ICommonConstants.SLASH_CHARACTER 

+        + patternData_p.getPluginId()

+      ).append(

+        PatternConstants.GENERATION_SOURCE_FOLDER

+      ).append(

+          ICommonConstants.SLASH_CHARACTER 

+        + FileHelper.convertPackageNameToFolderPath(

+            PatternConstants.PATTERN_GENERATED_BASE_PACKAGE 

+          + ICommonConstants.DOT_CHARACTER

+          + getPatternPackageName(patternData_p.getPattern())

+        )

+      );

+    return rootGeneratedPackageRelativePath.toString();

+  }  

+  

+  /**

+   * Get pattern generated EMF packages names.

+   * @param patternData_p

+   * @return a list of packages names. Empty if given pattern data is null.

+   */

+  public static List<String> getEMFGeneratedPackagesNames(PatternData patternData_p) {

+    // Precondition.

+    List<String> result = Collections.emptyList();

+    if (patternData_p == null) {

+      return result;

+    }

+    result = new ArrayList<String>(3);

+    // Compute base package name.

+    String baseGeneratedPackageName =

+        PatternConstants.PATTERN_GENERATED_BASE_PACKAGE 

+      + ICommonConstants.DOT_CHARACTER

+      + getPatternPackageName(patternData_p.getPattern());

+    // Add base package relative path.

+    result.add(baseGeneratedPackageName);

+    // Add implementation package relative path.

+    result.add(

+        baseGeneratedPackageName 

+      + IEgfGeneratorConstants.GENERATED_IMPL_JAVA_PACKAGE_SUFFIX

+    );

+    // Add tools package relative path.

+    result.add(

+        baseGeneratedPackageName 

+      + IEgfGeneratorConstants.GENERATED_UTIL_JAVA_PACKAGE_SUFFIX

+    );

+    return result;

+  }

+

+  /**

+   * Get generated pattern class description, if applicable.<br>

+   * That is, if the pattern engine leads to a compiled Java class, get its package and class names.<br>

+   * @param patternData_p

+   * @return null if not applicable, or could not be found (not compiled yet). Else, a (package name, class name) couple.

+   */

+  protected static Couple<String, String> getPatternTemplateClassDescription(PatternData patternData_p) {

+    Couple<String, String> result = null;

+    if (patternData_p == null) {

+      return result;

+    }

+    IDescriptor classDescriptor = new WorkspacePatternTemplateExtensionReader().readPatternTemplateExtension(

+      patternData_p.getJavaProject().getProject(), 

+      patternData_p.getPattern().getShortId()

+    );

+    if (classDescriptor == null) {

+      return result;

+    }

+    String templateClass = (String) classDescriptor.getValue(IPatternTemplateConstants.PATTERN_TEMPLATE_ATT_CLASS);

+    if (templateClass != null) {

+      String className = StringHelper.substringAfter(ICommonConstants.DOT_CHARACTER, templateClass);

+      String packageName = StringHelper.substringBefore(ICommonConstants.DOT_CHARACTER, templateClass);

+      result = new Couple<String, String>(packageName, className);

+    }

+    return result;

+  }

+

+  /**

+   * Get generated pattern class relative path, if any.<br>

+   * A pattern may not have a generated class, if :<br>

+   * <ul>

+   * <li>either the pattern engine type does not support a Java class transformation.</li>

+   * <li>or the pattern has not been produced yet, and thus no Java class can be found.</li>

+   * </ul>

+   * @param patternData_p

+   * @return null if it could not be found, else the workspace relative path to the Java class.

+   */

+  public static String getGeneratedPatternClassRelativePath(PatternData patternData_p) {

+    Couple<String, String> generatedPatternClassDescription = getPatternTemplateClassDescription(patternData_p);

+    if (generatedPatternClassDescription == null) {

+      return null;

+    }

+    IPath generatedPatternClassRelativePath = 

+      new Path(

+          ICommonConstants.SLASH_CHARACTER 

+        + patternData_p.getPluginId()

+      ).append(

+        PatternConstants.GENERATION_SOURCE_FOLDER

+      ).append(

+          ICommonConstants.SLASH_CHARACTER

+        + FileHelper.convertPackageNameToFolderPath(generatedPatternClassDescription.getKey())

+      ).append(

+          ICommonConstants.SLASH_CHARACTER 

+        + generatedPatternClassDescription.getValue()

+      ).addFileExtension(

+        IPatternConstants.JAVA_SOURCE_FILE_EXTENSION

+      );

+    return generatedPatternClassRelativePath.toString();

+  }

+    

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/GeneratedContentProducer.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/GeneratedContentProducer.java
new file mode 100644
index 0000000..9702d56
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/GeneratedContentProducer.java
@@ -0,0 +1,383 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.production;

+

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.List;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.constant.IPatternConstants;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.ProjectHelper;

+import org.eclipse.egf.common.helper.StringHelper;

+import org.eclipse.egf.common.misc.Couple;

+import org.eclipse.egf.core.CoreActivator;

+import org.eclipse.egf.model.Context;

+import org.eclipse.egf.model.FactoryComponent;

+import org.eclipse.egf.model.FactoryComponentInvocation;

+import org.eclipse.egf.model.ModelFactory;

+import org.eclipse.egf.model.data.helper.ModelHelper;

+import org.eclipse.egf.pattern.PatternActivator;

+import org.eclipse.egf.pattern.ecore.PatternConstants;

+import org.eclipse.egf.pattern.ecore.PatternHandler;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pattern.ecore.condition.ConditionClassOutput;

+import org.eclipse.egf.pattern.ecore.condition.IConditionConstants;

+import org.eclipse.egf.pattern.internal.ConditionMergeHelper;

+import org.eclipse.egf.pattern.internal.production.jet.JetProductionContributor;

+import org.eclipse.egf.pattern.production.template.TemplateHelper;

+import org.eclipse.egf.pattern.relations.ParameterRelation;

+import org.eclipse.egf.pde.EgfPdeActivator;

+import org.eclipse.egf.pde.pattern.plugin.command.PatternConditionExtensionFactory;

+import org.eclipse.egf.pde.plugin.command.IPluginChangesCommandRunner;

+

+/**

+ * The producer responsible for all generated content.

+ * @author Guillaume Brocard

+ */

+public class GeneratedContentProducer {

+  

+  /**

+   * Condition source code folder.

+   */

+  protected static final String CONDITION_SOURCE_FOLDER = "/src"; //$NON-NLS-1$

+  

+  /**

+   * Platform specific production contributor.

+   */

+  private IProductionContributor _contributor;

+  

+  /**

+   * Constructor.

+   */

+  public GeneratedContentProducer() {

+    _contributor = new JetProductionContributor();

+  }

+

+  /**

+   * Get associated production contributor.

+   * @return

+   */

+  public IProductionContributor getProductionContributor() {

+    return _contributor;

+  }

+

+  /**

+   * @see org.eclipse.egf.pattern.ecore.condition.IConditionProducer#produceConditionStructures(java.lang.String)

+   */

+  public void produceConditionStructures(String fileRelativePath_p) throws Exception {

+    PatternData patternData = new PatternHandler().load(fileRelativePath_p);

+    // Call sibling method.

+    produceConditionStructures(patternData);

+  }

+

+  /**

+   * Produce condition structures based on given pattern data.

+   * @param patternData_p

+   * @throws Exception

+   */

+  public void produceConditionStructures(PatternData patternData_p) throws Exception {

+    // Precondition.

+    if (patternData_p == null) {

+      return;

+    }

+    // Get all parameters.

+    List<ParameterRelation> parameters = patternData_p.getAllParameters();

+    // Preconditions.

+    if (parameters == null || parameters.isEmpty()) {

+      removeOldConditionStructures(patternData_p);

+      // Refresh project.

+      ProjectHelper.refreshProject(

+        patternData_p.getJavaProject().getProject(), 

+        null

+      );

+      return;

+    }

+    // Update condition Java class code, according to parameters list.

+    updateConditionClass(patternData_p, parameters);

+    // Replace matching pre/post templates.

+    replacePatternMatchingTemplates(patternData_p, parameters);

+    // Refresh project.

+    ProjectHelper.refreshProject(

+      patternData_p.getJavaProject().getProject(), 

+      null

+    );

+  }

+

+  /**

+   * Produce public parameters handler.

+   * @param patternData_p

+   */

+  protected void producePublicParametersHandler(PatternData patternData_p) {

+    // Create a factory component dynamically.

+    FactoryComponent fc = ModelHelper.createEmptyMinimalFC("GeneratePublicParametersHandler"); //$NON-NLS-1$

+    // Add required factory component invocation.

+    String generatorId = "asset.1212745121407.14"; //$NON-NLS-1$

+    FactoryComponentInvocation fcInvocation = ModelHelper.addFactoryComponentInvocation(

+      fc, 

+      generatorId

+    );

+    // Add a context.

+    Context context = ModelFactory.eINSTANCE.createContext();

+    fcInvocation.setContext(context);

+    // Add context elements.

+    String contributorId = PatternActivator.getDefault().getPluginID();

+    // Model path.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      generatorId, 

+      "contractElement.1212763579828.93", //$NON-NLS-1$

+      patternData_p.getRealRelativePath(),

+      contributorId

+    );

+    // Pattern name.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      generatorId, 

+      "contractElement.1212763518024.91", //$NON-NLS-1$ 

+      patternData_p.getPatternName(), 

+      contributorId

+    );

+    // Plug-in ID.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      generatorId, 

+      "contractElement.1212763360724.90", //$NON-NLS-1$ 

+      patternData_p.getPluginId(), 

+      contributorId

+    );

+    // Execute it.

+    CoreActivator.getDefault().generateFactoryComponentSynchronously(fc);

+  }

+

+  /**

+   * Get condition class content as for given pattern data.

+   * @param patternData_p

+   * @return null if an error occurred, {@link ICommonConstants#EMPTY_STRING} if it could not be generated.

+   */

+  protected String getConditionClassContent(PatternData patternData_p) {

+    // Result output container.

+    ConditionClassOutput.getSharedInstance().reset();

+    // Create a factory component dynamically.

+    FactoryComponent fc = ModelHelper.createEmptyMinimalFC("GenerateConditionClass"); //$NON-NLS-1$

+    // Add required factory component invocation.

+    String generatorId = "asset.1213692164306.87"; //$NON-NLS-1$

+    FactoryComponentInvocation fcInvocation = ModelHelper.addFactoryComponentInvocation(

+      fc, 

+      generatorId

+    );

+    // Add a context.

+    Context context = ModelFactory.eINSTANCE.createContext();

+    fcInvocation.setContext(context);

+    // Add context elements.

+    String contributorId = PatternActivator.getDefault().getPluginID();

+    // Model path.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      generatorId, 

+      "contractElement.1213715622825.42", //$NON-NLS-1$

+      patternData_p.getRealRelativePath(),

+      contributorId

+    );

+    // Execute it.

+    CoreActivator.getDefault().generateFactoryComponentSynchronously(fc);

+    // Extract result.

+    return ConditionClassOutput.getSharedInstance().getGeneratedConditionClassContent(patternData_p.getPattern().getId());

+  }

+

+  /**

+   * Update condition class if it already exists, else create it with empty content.

+   * @param patternData_p

+   * @param parameters_p

+   * @return

+   */

+  protected void updateConditionClass(PatternData patternData_p, List<ParameterRelation> parameters_p) throws Exception {

+    // Resulting content is generated.

+    String resultingContent = getConditionClassContent(patternData_p);

+    if (resultingContent == null || ICommonConstants.EMPTY_STRING.equals(resultingContent)) {

+      throw new IllegalArgumentException();

+    }

+    // Check existing condition class.

+    String conditionClassRelativePath = getConditionFileRelativePath(patternData_p);

+    // Merge required.

+    if (FileHelper.exists(conditionClassRelativePath)) {

+      resultingContent = ConditionMergeHelper.merge(

+        resultingContent, 

+        FileHelper.readFile(conditionClassRelativePath)

+      );

+    }

+    // Write result to file.

+    FileHelper.writeFile(conditionClassRelativePath, true, resultingContent);

+    // Update plugin.xml content accordingly.

+    IPluginChangesCommandRunner runner = EgfPdeActivator.getDefault().getPluginChangesCommandRunner(); 

+    runner.performChangesOnPlugin(

+      patternData_p.getPluginId(), 

+      Collections.singletonList(

+        PatternConditionExtensionFactory.setPatternConditionExtension(

+          patternData_p.getPattern().getId(), 

+          new StringBuilder(PatternConstants.PATTERN_CONDITION_GENERATED_BASE_PACKAGE)

+            .append(ICommonConstants.DOT_CHARACTER)

+            .append(getConditionClassName(patternData_p))

+            .toString()

+        )

+      )

+    );

+  }

+

+  /**

+   * Get condition file relative path from given parameters.

+   * @param patternData_p

+   * @return

+   */

+  public static String getConditionFileRelativePath(PatternData patternData_p) {

+    // Return computed name.

+    return getGeneratedClassRelativePath(

+      patternData_p.getPluginId(), 

+      CONDITION_SOURCE_FOLDER, 

+      PatternConstants.PATTERN_CONDITION_GENERATED_BASE_PACKAGE, 

+      getConditionClassName(patternData_p)

+    );

+  }

+

+  /**

+   * Get generated class relative path.

+   * @param pluginId_p

+   * @param sourceFolder_p

+   * @param packageName_p

+   * @param className_p

+   * @return

+   */

+  public static String getGeneratedClassRelativePath(

+    String pluginId_p, 

+    String sourceFolder_p, 

+    String packageName_p, 

+    String className_p

+  ) {

+    // Preconditions.

+    if (pluginId_p == null || sourceFolder_p == null || packageName_p == null || className_p == null) {

+      return ICommonConstants.EMPTY_STRING;

+    }

+    // Compute file relative path (does imply that dot-separated package name is converted into folder path).           

+    return 

+      new StringBuilder(pluginId_p)

+        .append(sourceFolder_p)

+        .append(ICommonConstants.SLASH_CHARACTER)

+        .append(FileHelper.convertPackageNameToFolderPath(packageName_p))

+        .append(ICommonConstants.SLASH_CHARACTER)

+        .append(className_p)

+        .append(ICommonConstants.DOT_CHARACTER)

+        .append(IPatternConstants.JAVA_SOURCE_FILE_EXTENSION)

+        .toString();

+  }

+

+  /**

+   * Get condition class name from pattern data.

+   * @param patternData_p

+   * @return

+   */

+  public static String getConditionClassName(PatternData patternData_p) {

+    return getClassName(

+      patternData_p.getPatternName(), 

+      IConditionConstants.CONDITION_CLASS_NAME_SUFFIX

+    );

+  }

+

+  /**

+   * Get generated class name from pattern one and suffix.

+   * @param patternName_p

+   * @param suffix_p

+   * @return

+   */

+  public static String getClassName(String patternName_p, String suffix_p) {

+    return 

+      new StringBuilder(StringHelper.toUpperFirst(patternName_p))

+        .append(suffix_p)

+        .toString();

+  }

+

+  /**

+   * Replace pre and post pattern matching templates that are included in the generated pattern template.

+   * @param patternData_p

+   * @param parameters_p

+   */

+  protected void replacePatternMatchingTemplates(PatternData patternData_p, List<ParameterRelation> parameters_p) {

+    // (Re-)Create template files content.

+    Couple<StringBuilder, StringBuilder> resultingTemplates = _contributor.createPatternMatchingTemplates(

+      patternData_p, 

+      parameters_p

+    );

+    // Save templates files.

+    String patternShortId = patternData_p.getPattern().getShortId();

+    String pluginId = patternData_p.getPluginId();

+    FileHelper.writeFile(

+      TemplateHelper.getTemplateRelativePath(

+        patternShortId, 

+        pluginId, 

+        PatternConstants.GENERATE_PRE_MATCHING_METHOD_NAME, 

+        null

+      ), 

+      true,

+      resultingTemplates.getKey().toString()

+    );

+    FileHelper.writeFile(

+      TemplateHelper.getTemplateRelativePath(

+        patternShortId, 

+        pluginId, 

+        PatternConstants.GENERATE_POST_MATCHING_METHOD_NAME, 

+        null

+      ), 

+      true,

+      resultingTemplates.getValue().toString()

+    );

+  }

+

+  /**

+   * Remove no longer needed condition structures, if any.<br>

+   * That might happen, when the pattern is loosing all its parameters, due to a user decision.

+   * @param patternData_p

+   */

+  protected void removeOldConditionStructures(PatternData patternData_p) {

+    // Delete existing condition class, if any.

+    String conditionClassRelativePath = getConditionFileRelativePath(patternData_p);

+    if (FileHelper.exists(conditionClassRelativePath)) {

+      FileHelper.deleteFile(conditionClassRelativePath);

+    }

+    String patternShortId = patternData_p.getPattern().getShortId();

+    String pluginId = patternData_p.getPluginId();

+    // Delete pre-matching template, if any.

+    String preMatchingRelativePath = TemplateHelper.getTemplateRelativePath(

+      patternShortId, 

+      pluginId, 

+      PatternConstants.GENERATE_PRE_MATCHING_METHOD_NAME, 

+      null

+    );

+    if (FileHelper.exists(preMatchingRelativePath)) {

+      FileHelper.deleteFile(preMatchingRelativePath);

+    }

+    // Delete post-matching template, if any.

+    String postMatchingRelativePath = TemplateHelper.getTemplateRelativePath(

+      patternShortId, 

+      pluginId, 

+      PatternConstants.GENERATE_POST_MATCHING_METHOD_NAME, 

+      null

+    );

+    if (FileHelper.exists(postMatchingRelativePath)) {

+      FileHelper.deleteFile(postMatchingRelativePath);

+    }

+    // Ask for reconstruction of pre and post matching, if required.

+    replacePatternMatchingTemplates(

+      patternData_p, 

+      new ArrayList<ParameterRelation>(0)

+    );

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/IProductionContributor.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/IProductionContributor.java
new file mode 100644
index 0000000..bcbdaa1
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/IProductionContributor.java
@@ -0,0 +1,57 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.production;

+

+import java.util.List;

+

+import org.eclipse.egf.common.misc.Couple;

+import org.eclipse.egf.pattern.ecore.AnnotationHandler;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pattern.relations.ParameterRelation;

+

+

+/**

+ * A production contributor.<br>

+ * Typically handles a specific platform production code.

+ * @author Guillaume Brocard

+ */

+public interface IProductionContributor {

+  

+  /**

+   * Create pre/post pattern matching templates.<br>

+   * Those are supposed to be produced in the generated templates folder.<br>

+   * Their physical form depends on the template engine used (as for the file extension for instance).

+   * @param patternData_p The structure containing most of the pattern required data for generation.

+   * @param parameters_p The fully resolved list of parameters (including parent hierarchy) for considered pattern.

+   * @return A couple of (pre-matching, post-matching) {@link StringBuilder} containing resulting template code, null if there is no such content.

+   */

+  public Couple<StringBuilder, StringBuilder> createPatternMatchingTemplates(PatternData patternData_p, List<ParameterRelation> parameters_p);

+

+  /**

+   * Compile given template, if applicable.

+   * @param generatedTemplatePath_p

+   * @param patternData_p

+   * @return

+   * @throws Exception

+   */

+  public boolean compileTemplate(String generatedTemplatePath_p, PatternData patternData_p) throws Exception;

+

+  /**

+   * Fill, if applicable, generateHeader method of the pattern, if it does not exist or is empty.<br>

+   * Given content should ensure pattern compilation phase, whether this lead to a valid status or not.<br>

+   * The user will then be able to choose a more convenient content.

+   * @param patternData_p

+   * @param handler_p A usable annotation handler, null if none.

+   * @throws Exception

+   */

+  public void fillGenerateHeader(PatternData patternData_p, AnnotationHandler handler_p) throws Exception;

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/Messages.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/Messages.java
new file mode 100644
index 0000000..ff70210
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/Messages.java
@@ -0,0 +1,38 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.production;

+

+import org.eclipse.osgi.util.NLS;

+

+/**

+ * @author brocard

+ */

+public class Messages extends NLS {

+  

+  private static final String BUNDLE_NAME = "org.eclipse.egf.pattern.production.messages"; //$NON-NLS-1$

+  

+  public static String PatternTemplateProducer_PatternProductionErrorMessage;

+  

+  public static String PatternProducer_PatternProductionErrorTitle;

+  public static String PatternProducer_ProgressReporting_GetPath;

+  public static String PatternProducer_ProgressReporting_JavaToResult;

+  public static String PatternProducer_ProgressReporting_PatternToJava;

+  public static String PatternProducer_ProgressReporting_Title;

+  

+  static {

+    // initialize resource bundle

+    NLS.initializeMessages(BUNDLE_NAME, Messages.class);

+  }

+

+  private Messages() {

+    // Static initialization

+  }

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/PatternProducer.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/PatternProducer.java
new file mode 100644
index 0000000..aaf5817
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/PatternProducer.java
@@ -0,0 +1,439 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.production;

+

+import java.util.ArrayList;

+import java.util.List;

+import java.util.Set;

+

+import org.apache.log4j.Logger;

+

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.core.runtime.SubMonitor;

+import org.eclipse.jdt.core.IJavaProject;

+import org.eclipse.pde.core.plugin.IPluginModelBase;

+import org.eclipse.pde.core.plugin.PluginRegistry;

+

+import org.eclipse.emf.codegen.ecore.genmodel.GenJDKLevel;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.constant.IPatternTemplateConstants;

+import org.eclipse.egf.common.descriptor.IDescriptor;

+import org.eclipse.egf.common.helper.ExtensionPointHelper;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.MathHelper;

+import org.eclipse.egf.common.misc.Couple;

+import org.eclipse.egf.common.progress.ProductionProgressMonitor;

+import org.eclipse.egf.common.progress.ProgressReporter;

+import org.eclipse.egf.core.CoreActivator;

+import org.eclipse.egf.fc.generator.java.model.EcoreGenModelGenerator;

+import org.eclipse.egf.model.Context;

+import org.eclipse.egf.model.FactoryComponent;

+import org.eclipse.egf.model.FactoryComponentInvocation;

+import org.eclipse.egf.model.ModelFactory;

+import org.eclipse.egf.model.data.helper.ModelHelper;

+import org.eclipse.egf.pattern.PatternActivator;

+import org.eclipse.egf.pattern.ecore.PatternConstants;

+import org.eclipse.egf.pattern.ecore.PatternSeeker;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pattern.production.template.TemplateHelper;

+

+

+/**

+ * Pattern producer.<br>

+ * Can either produce a library of patterns, or a single pattern.

+ * @author brocard

+ */

+public class PatternProducer {

+  

+  /**

+   * Log4j reference logger.

+   */

+  private static final Logger __logger = Logger.getLogger(PatternProducer.class.getPackage().getName());

+  

+  /**

+   * Java builder factory component id.

+   */

+  protected static final String JAVA_BUILDER_FACTORY_COMPONENT_ID = "java.builder.asset"; //$NON-NLS-1$

+  

+  /**

+   * Java builder project name contract element id.

+   */

+  protected static final String JAVA_BUILDER_FACTORY_COMPONENT_CONTRACT_FACTORY_COMPONENT_PROJECT_NAME = "java.builder.asset.contract.assetProjectName"; //$NON-NLS-1$

+    

+  /**

+   * Java code generator jdk compliance level contract element id.

+   */

+  protected static final String JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_JDK_COMPLIANCE_LEVEL = "javaCodeGeneratorAsset.contract.jdkComplianceLevel"; //$NON-NLS-1$

+  

+  /**

+   * Java code generator genModel generator contract element id.

+   */

+  protected static final String JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_GEN_MODEL_GENERATOR = "javaCodeGeneratorAsset.contract.genModelGenerator"; //$NON-NLS-1$

+  

+  /**

+   * Java code generator base package contract element id.

+   */

+  protected static final String JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_BASE_PACKAGE = "javaCodeGeneratorAsset.contract.basePackage"; //$NON-NLS-1$

+  

+  /**

+   * Java code generator project name contract element id.

+   */

+  protected static final String JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_FACTORY_COMPONENT_PROJECT_NAME = "javaCodeGeneratorAsset.contract.assetProjectName"; //$NON-NLS-1$

+  

+  /**

+   * Java code generator input path contract element id.

+   */

+  protected static final String JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_INPUT_PATH = "javaCodeGeneratorAsset.contract.inputPath"; //$NON-NLS-1$

+  

+  /**

+   * Java code generator model directory contract element id.

+   */

+  protected static final String JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_MODEL_DIRECTORY = "javaCodeGeneratorAsset.contract.modelDirectory"; //$NON-NLS-1$

+  

+  /**

+   * Java code generator factory component id.

+   */

+  protected static final String JAVA_CODE_GENERATOR_FACTORY_COMPONENT_ID = "javaCodeGeneratorAsset"; //$NON-NLS-1$

+  

+  /**

+   * Pattern seeker reference.

+   */

+  private static PatternSeeker _seeker; 

+

+  /**

+   * Constructor.

+   */

+  public PatternProducer() {

+    //Nothing to do

+  }

+

+  /**

+   * Get pattern seeker.

+   * @return

+   */

+  protected static PatternSeeker getPatternSeeker() {

+    if (_seeker == null) {

+      // Do look for patterns in workspace.

+      _seeker = new PatternSeeker(true);

+    }

+    return _seeker;

+  }

+

+  /**

+   * Build the java project holding the currently produced pattern.

+   * @param patternData_p

+   * @return

+   */

+  protected boolean buildPatternProject(PatternData patternData_p) {

+    // Create a factory component dynamically which goal is to build the pattern project.

+    // It is referencing java builder factory component.

+    String referencedFcId = JAVA_BUILDER_FACTORY_COMPONENT_ID;

+    Couple<FactoryComponent, Context> buildProjectFc = createFactoryComponentSkeleton(

+      "patternProducer.factoryComponent.buildProject",  //$NON-NLS-1$ 

+      referencedFcId

+    );

+    // Fill context.

+    // FactoryComponent project name.

+    ModelHelper.addReferencingContractContextElement(

+      buildProjectFc.getValue(), 

+      referencedFcId, 

+      JAVA_BUILDER_FACTORY_COMPONENT_CONTRACT_FACTORY_COMPONENT_PROJECT_NAME,

+      patternData_p.getPluginId(), 

+      PatternActivator.getDefault().getPluginID()

+    );

+    return generateFactoryComponent(buildProjectFc.getKey());

+  }

+  

+  /**

+   * Create a factory component with given name.<br>

+   * By default, a factory with a unique production plan is added to the newly created factory component.<br>

+   * This production plan contains a factory component invocation containing a default context.<br>

+   * This context should be filled up.

+   * @param fcName_p

+   * @return

+   */

+  protected static Couple<FactoryComponent, Context> createFactoryComponentSkeleton(String fcName_p, String referencedFcId_p) {

+    // Create a factory component dynamically.

+    FactoryComponent fc = ModelHelper.createEmptyMinimalFC(fcName_p);

+    // Add required factory component invocation.

+    FactoryComponentInvocation fcInvocation = ModelHelper.addFactoryComponentInvocation(

+      fc, 

+      referencedFcId_p

+    );

+    // Add a default context.

+    Context context = ModelFactory.eINSTANCE.createContext();

+    fcInvocation.setContext(context);

+    return new Couple<FactoryComponent, Context>(fc, context);

+  }

+

+  /**

+   * Generate given factory component in current thread.

+   * @param fc_p

+   * @return

+   */

+  protected static boolean generateFactoryComponent(FactoryComponent fc_p) {

+    return CoreActivator.getDefault().generateFactoryComponentSynchronously(fc_p);

+  }

+

+  /**

+   * Generate pattern classes.<br>

+   * That is generate classes that are describing the pattern structure as an object one.<br>

+   * Such classes are composed of a <i>String generate()</i> method, and several internal pattern methods.<br>

+   * Calling <i>generate()</i> method results in getting the content of a new template file that is indeed acting as the whole pattern, when applied.<br>

+   * When all classes are generated, also force project build so that they may subsequently be used.

+   * @param patternData_p

+   * @return

+   */

+  protected static boolean generatePatternClasses(PatternData patternData_p) {

+    IJavaProject javaProject = patternData_p.getJavaProject();

+    // Precondition.

+    // Only produce pattern for in-development patterns (that is not do-able for already deployed patterns).

+    if (javaProject == null) {

+      return false;

+    }

+    // Should fix bug prod00015930

+    try {

+      // That might be a good time to generate pre and post matching templates, if applicable.

+      GeneratedContentProducer conditionProducer = new GeneratedContentProducer();

+      conditionProducer.produceConditionStructures(patternData_p);

+      // Fill generate header, if none is provided.

+      conditionProducer.getProductionContributor().fillGenerateHeader(patternData_p, null);

+    } catch (Exception exception_p) {

+      StringBuilder loggerMessage = new StringBuilder("PatternProducer.generatePatternClasses(..) _ "); //$NON-NLS-1$

+      __logger.warn(loggerMessage.toString(), exception_p);

+    }

+    // End of fix for prod00015930

+    // Make sure all dependencies are already compiled.

+    ensurePatternsJavaFiles(patternData_p.getPatternDependenciesIds());

+    // Create a factory component dynamically, used to produce the java code for this pattern.

+    // It is referencing java code generator factory component.

+    String referencedFcId = JAVA_CODE_GENERATOR_FACTORY_COMPONENT_ID;

+    Couple<FactoryComponent, Context> producePatternCouple = createFactoryComponentSkeleton(

+      "patternProducer.factoryComponent.ecoreToJava",  //$NON-NLS-1$ 

+      referencedFcId

+    );

+    // Get context.

+    Context context = producePatternCouple.getValue();

+    // Fill context up.

+    context.getContextElements().clear();

+    String contributorId = PatternActivator.getDefault().getPluginID();

+    // Model directory.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      referencedFcId, 

+      JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_MODEL_DIRECTORY,

+      new Path(PatternConstants.GENERATION_SOURCE_FOLDER).segment(0), 

+      contributorId

+    );

+    // Input path.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      referencedFcId, 

+      JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_INPUT_PATH, 

+      patternData_p.getRealRelativePath(), 

+      contributorId

+    );

+    // FactoryComponent project name.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      referencedFcId, 

+      JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_FACTORY_COMPONENT_PROJECT_NAME, 

+      patternData_p.getPluginId(), 

+      contributorId

+    );

+    // Base package.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      referencedFcId, 

+      JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_BASE_PACKAGE,

+      PatternConstants.PATTERN_GENERATED_BASE_PACKAGE, 

+      contributorId

+    );

+    // GenModel generator.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      referencedFcId, 

+      JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_GEN_MODEL_GENERATOR,

+      EcoreGenModelGenerator.class.getName(), 

+      contributorId

+    );

+    // Jdk compliance level.

+    ModelHelper.addReferencingContractContextElement(

+      context, 

+      referencedFcId, 

+      JAVA_CODE_GENERATOR_FACTORY_COMPONENT_CONTRACT_ELEMENT_JDK_COMPLIANCE_LEVEL,

+      GenJDKLevel.JDK50_LITERAL.getLiteral(), 

+      contributorId

+    );

+    return generateFactoryComponent(producePatternCouple.getKey());

+  }

+

+  /**

+   * Ensure all identified patterns are indeed usable as java classes.<br>

+   * That is, if one of these patterns is being developed and has never been generated, do use its ecore file to generate its java classes form, and compile

+   * them.

+   * @param fullIds_p

+   */

+  protected static void ensurePatternsJavaFiles(Set<String> fullIds_p) {

+    // Precondition.

+    if (fullIds_p == null) {

+      return;

+    }

+    // Get list of pattern paths.

+    List<PatternData> patternsData = new ArrayList<PatternData>(0);

+    for (String patternId : fullIds_p) {

+      patternsData.addAll(getPatternSeeker().getPatternsData(patternId));

+    }

+    // Now just generate pattern classes for all selected ones.

+    for (PatternData patternData : patternsData) {

+      // Generate pattern java classes and ensure build of containing project.

+      generatePatternClasses(patternData);

+    }

+  }

+

+  /**

+   * Take care of the whole production chain for given patterns data.

+   * @param data_p

+   * @param monitor_p

+   * @param ticksCount_p

+   * @return

+   */

+  protected static boolean handlePatternsProduction(List<PatternData> data_p, SubMonitor monitor_p, int ticksCount_p) {

+    boolean result = true;

+    // How many ticks should monitor eat each time ?

+    int stepCount = ticksCount_p / data_p.size();

+    // Cycle through pattern paths.

+    for (PatternData patternData : data_p) {

+      // Monitor each pattern to produce.

+      ProductionProgressMonitor monitor = new ProductionProgressMonitor(

+        monitor_p, 

+        patternData.getPatternLogicalName(), 

+        stepCount

+      );

+      // Check hosting java project.

+      boolean proceed = patternData.getJavaProject() != null;

+      if (proceed) {

+        // Convert pattern ecore file to java files.

+        proceed = generatePatternClasses(patternData);

+      }

+      result &= proceed;

+      // Acknowledge each pattern production.

+      monitor.end();

+    }

+    return result;

+  }

+

+  /**

+   * Produce identified pattern.

+   * @param fullId_p The absolute id of either a library or a pattern.

+   * @return

+   */

+  public static boolean producePatterns(String fullId_p, IProgressMonitor progressMonitor_p) {

+    boolean result = fullId_p != null;

+    // Precondition.

+    if (result == false) {

+      progressMonitor_p.done();

+      return result;

+    }

+    try {

+      // Do produce the patterns.

+      String productionMessage = Messages.PatternProducer_ProgressReporting_Title + fullId_p;

+      // Convert progress monitor to sub monitor.

+      SubMonitor subMonitor = SubMonitor.convert(progressMonitor_p, productionMessage, ProgressReporter.TASK_DEFAULT_TICKS_COUNT);

+      // Get pattern path.

+      int ticksCount = MathHelper.multiply(ProgressReporter.TASK_DEFAULT_TICKS_COUNT, 0.1f);

+      List<PatternData> patternsData = getPatternSeeker().getPatternsData(fullId_p);

+      int patternsCount = patternsData.size();

+      subMonitor.worked(ticksCount);

+      ticksCount = ProgressReporter.TASK_DEFAULT_TICKS_COUNT - ticksCount;

+      subMonitor.setWorkRemaining(ticksCount);

+      result = (patternsCount > 0);

+      // Got the patterns paths, go on with production.

+      if (result) {

+        // Generate patterns classes.

+        handlePatternsProduction(patternsData, subMonitor, ticksCount);

+        subMonitor.setWorkRemaining(0);

+      }

+    } finally {

+      // Whatever happened, always complete the progress monitor.

+      progressMonitor_p.done();

+      // Return false if cancellation happened.

+      result &= progressMonitor_p.isCanceled() == false;

+    }

+    return result;

+  }

+  

+  /**

+   * Generate identified pattern.<br>

+   * That is, generate resulting template and return it as a string.<br>

+   * The resulting template does include neither the header, nor the footer.<br>

+   * This method should only be called in the case of an inclusion of the identified pattern in another one.

+   * @param fullId_p

+   * @param classLoader_p

+   * @return

+   */

+  public String generatePatterns(String fullId_p, Object classLoader_p) {

+    String result = ICommonConstants.EMPTY_STRING;

+    // Precondition.

+    if (fullId_p == null || classLoader_p instanceof ClassLoader == false) {

+      return result;

+    }

+    // Get class loader.

+    ClassLoader usableClassLoader = (ClassLoader) classLoader_p;

+    // Get pattern paths.

+    List<PatternData> patternsData = getPatternSeeker().getPatternsData(fullId_p);

+    // Check that there is indeed some work to do.

+    if (patternsData.size() < 0) {

+      return result;

+    }

+    StringBuilder resultingBuilder = new StringBuilder();

+    // Now, go on with the good work.

+    for (PatternData patternData : patternsData) {

+      // Try and transform ecore pattern file to java classes, if it is necessary.

+      generatePatternClasses(patternData);

+      // Then get pattern template as a string.

+      String patternTemplate = PatternTemplateProducer.getPatternTemplateAsString(patternData, usableClassLoader);

+      if (patternTemplate != null) {

+        resultingBuilder.append(patternTemplate);

+      }

+    }

+    return resultingBuilder.toString();

+  } 

+  

+  /**

+   * Clean pattern template structure.

+   * @param javaProject_p

+   * @param descriptor_p

+   */  

+  public static void cleanGeneratedStructures(IJavaProject javaProject_p, IDescriptor descriptor_p) {

+    if (javaProject_p == null || descriptor_p == null) {

+      return;

+    }

+    // Process only Workspace Plugin

+    IPluginModelBase model = PluginRegistry.findModel(javaProject_p.getProject());

+    if (model == null) {

+      return;

+    }

+    // Retrieve needed informations from IDescriptor

+    String patternShortId = (String) descriptor_p.getValue(ExtensionPointHelper.ATT_ID);

+    String patternTemplatePath = (String) descriptor_p.getValue(IPatternTemplateConstants.PATTERN_TEMPLATE_ATT_PATH);

+    String patternTemplateClass = (String) descriptor_p.getValue(IPatternTemplateConstants.PATTERN_TEMPLATE_ATT_CLASS);

+    // Clean generated templates if any

+    FileHelper.deleteResource(

+      TemplateHelper.getTemplateRootIFolder(javaProject_p),

+      TemplateHelper.getGeneratedPatternTemplateIFolder(javaProject_p, patternShortId),

+      true

+    );

+  }  

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/PatternTemplateProducer.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/PatternTemplateProducer.java
new file mode 100644
index 0000000..a6f4022
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/PatternTemplateProducer.java
@@ -0,0 +1,285 @@
+/**

+ * <copyright>

+ *

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ *

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *

+ * </copyright>

+ * 

+ */

+package org.eclipse.egf.pattern.production;

+

+import java.lang.reflect.Field;

+import java.lang.reflect.Method;

+import java.util.Collections;

+

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.jdt.core.IJavaProject;

+import org.eclipse.osgi.util.NLS;

+import org.eclipse.pde.core.plugin.IPluginModelBase;

+import org.eclipse.pde.core.plugin.PluginRegistry;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.constant.IPatternConstants;

+import org.eclipse.egf.common.constant.IPatternTemplateConstants;

+import org.eclipse.egf.common.descriptor.IDescriptor;

+import org.eclipse.egf.common.helper.ExtensionPointHelper;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.helper.JavaHelper;

+import org.eclipse.egf.common.helper.ProjectHelper;

+import org.eclipse.egf.console.EGFConsolePlugin;

+import org.eclipse.egf.pattern.Pattern;

+import org.eclipse.egf.pattern.PatternActivator;

+import org.eclipse.egf.pattern.ecore.PatternConstants;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+import org.eclipse.egf.pattern.production.template.TemplateHelper;

+import org.eclipse.egf.pde.EgfPdeActivator;

+import org.eclipse.egf.pde.pattern.plugin.command.PatternTemplateExtensionFactory;

+import org.eclipse.egf.pde.plugin.command.IPluginChangesCommandRunner;

+

+

+public class PatternTemplateProducer {

+  

+  /**

+   * Debug mode.

+   */  

+  private static boolean DEBUG = PatternActivator.getDefault().isDebugging(); 

+  

+  /**

+   * Emf factory create methods prefix.

+   */

+  protected static final String PATTERN_FACTORY_CREATE_METHOD_PREFIX = "create"; //$NON-NLS-1$

+  

+  /**

+   * Emf factory name prefix.

+   */

+  protected static final String PATTERN_FACTORY_NAME_SUFFIX = "Factory"; //$NON-NLS-1$

+  

+  /**

+   * Emf factory attribute name from interface to implementation.

+   */

+  protected static final String PATTERN_FACTORY_ATTRIBUTE_NAME = "eINSTANCE"; //$NON-NLS-1$

+      

+  /**

+   * Generate resulting template for given pattern data.

+   * @param patternData_p

+   * @return

+   */

+  public static boolean generateTemplate(final PatternData patternData_p) {

+    try {

+      // Do produce the pattern.

+      // That is instantiate its generated class, and invoke production method.

+      String patternTemplatePath = doProducePattern(patternData_p);

+      if (patternTemplatePath == null) {

+        return false;

+      }

+      // Should template be compiled ?

+      if (patternData_p.getProductionOptionsHandler().shouldCompileTemplate()) {

+        // Now that the template is created, compile it.

+        if (compileResultingTemplate(patternTemplatePath, patternData_p) == false) {

+          return false;

+        }

+      }

+    } catch (Exception e) {

+      if (DEBUG) {

+        EGFConsolePlugin.getConsole().logThrowable(

+          NLS.bind(Messages.PatternTemplateProducer_PatternProductionErrorMessage, patternData_p.getPatternLogicalName()), 

+          e

+        );

+      }

+      PatternActivator.getDefault().log(e);      

+      return false;

+    }

+    return true;

+  }  

+  

+  /**

+   * Produce identified pattern.<br>

+   * Do instantiate pattern generated class, and call its production method.<br>

+   * As a result, a new template file is created.

+   * @param patternData_p

+   * @return Resulting template file (relative to workspace) path.

+   * @throws Exception

+   */

+  public static String doProducePattern(PatternData patternData_p) throws Exception {

+    // Instantiate pattern.

+    ClassLoader classLoader[] = new ClassLoader[] { null };

+    Pattern pattern = instantiatePattern(patternData_p, classLoader);

+    // Unable to instantiate pattern.

+    if (pattern == null) {

+      return null;

+    }

+    // Call the pattern 'produce' method.

+    String templateContent = pattern.produce(classLoader[0]);

+    // Write a new template file to the project, with the content set to new one.

+    String patternTemplatePath = TemplateHelper.getPatternTemplatePath(patternData_p);

+    if (FileHelper.writeFile(patternTemplatePath, true, templateContent)) {

+      return patternTemplatePath;

+    }

+    return null;

+  }

+  

+  /**

+   * Instantiate identified pattern.

+   * @param patternData_p The pattern required data.

+   * @param classLoader_p The class loader used to instantiate the pattern as an array of one element.<br>

+   *          Can be null, it is then created using given pattern path java project, and returned in given array (as the only element).

+   * @return

+   * @throws Exception

+   */

+  public static Pattern instantiatePattern(PatternData patternData_p, ClassLoader[] classLoader_p) throws Exception {

+    // Precondition.

+    if (patternData_p == null) {

+      return null;

+    }

+    // Set some useful variables

+    IJavaProject javaProject = patternData_p.getJavaProject();

+    ClassLoader classLoader = classLoader_p[0];    

+    // Build the path string to the java resource we need to instantiate

+    String pathString = new StringBuilder(PatternConstants.PATTERN_GENERATED_BASE_PACKAGE)

+    .append(ICommonConstants.DOT_CHARACTER)

+    .append(GeneratedContentHelper.getPatternPackageName(patternData_p.getPattern()))

+    .append(ICommonConstants.DOT_CHARACTER)

+    .append(GeneratedContentHelper.getPatternClassName(patternData_p.getPattern()))

+    .append(PATTERN_FACTORY_NAME_SUFFIX)

+    .toString();

+    // Locate the resource to instantiate, if not found, we skip it

+    // This check is less expensive than a classloader building and the according loading attempt

+    IFile file = JavaHelper.getJavaSourceFile(

+      javaProject, 

+      new Path(FileHelper.convertPackageNameToFolderPath(pathString)).addFileExtension(IPatternConstants.JAVA_SOURCE_FILE_EXTENSION)

+    );

+    if (file == null) {

+      return null;

+    }

+    // Build a classloader able to load our pattern

+    // Only build and create class loader for an in-development pattern.

+    if (javaProject != null) {

+      // Create the class loader.

+      // Use pattern plugin classloader as parent one.

+      classLoader = ProjectHelper.getClassLoaderFor(javaProject, PatternActivator.getDefault().getClass().getClassLoader());

+      if (classLoader == null) { // Try using given one instead.

+        classLoader = classLoader_p[0];

+      } else {

+        // Return created class loader.

+        classLoader_p[0] = classLoader;

+      }

+    }

+    // Precondition.

+    if (classLoader == null) {

+      return null;

+    }

+    // Get the pattern factory.

+    Class<?> factoryInterface = null;

+    try {

+      factoryInterface = classLoader.loadClass(pathString);

+    } catch (ClassNotFoundException cnfe) {

+      // We can do nothing so we leave

+      return null;

+    }    

+    // And its instance through the eInstance EMF factory attribute.

+    Field factoryEInstance = factoryInterface.getDeclaredField(PATTERN_FACTORY_ATTRIBUTE_NAME);

+    Object factoryObject = factoryEInstance.get(factoryInterface);

+    // Now instantiate the pattern java class, previously generated and compiled.

+    Method createMethod = factoryInterface.getDeclaredMethod(

+      new StringBuilder(PATTERN_FACTORY_CREATE_METHOD_PREFIX)

+        .append(patternData_p.getPatternName())

+        .toString(), 

+      (Class[]) null

+    );

+    // Invoke and return it

+    return (Pattern) createMethod.invoke(factoryObject, (Object[]) null);

+  }  

+  

+  /**

+   * Do compile/interpret resulting template, if applicable, into a resulting java class.<br>

+   * Resulting class is not compiled, until a java compiler is applied.

+   * @param patternTemplatePath_p

+   * @param patternData_p

+   * @return

+   * @throws Exception

+   */

+  public static boolean compileResultingTemplate(String patternTemplatePath_p, PatternData patternData_p) throws Exception {

+    return new GeneratedContentProducer().getProductionContributor().compileTemplate(patternTemplatePath_p, patternData_p);

+  } 

+    

+  /**

+   * Get pattern template as a string.

+   * @param patternData_p

+   * @param classLoader_p

+   * @return the resulting template as a string, or empty string if an error occurred.

+   */

+  protected static String getPatternTemplateAsString(PatternData patternData_p, ClassLoader classLoader_p) {

+    String result = ICommonConstants.EMPTY_STRING;

+    // Instantiate pattern.

+    ClassLoader classLoader[] = new ClassLoader[] { classLoader_p };

+    try {

+      Pattern pattern = instantiatePattern(patternData_p, classLoader);

+      // Get result by generating instantiated pattern.

+      if (pattern != null) {

+        result = pattern.generate(classLoader[0]);

+      }

+    } catch (Exception e) {

+      String msg = new String("PatternTemplateProducer.getPatternTemplateAsString(..) _ "); //$NON-NLS-1$

+      if (DEBUG) {

+        EGFConsolePlugin.getConsole().logThrowable(msg, e);

+      }

+      PatternActivator.getDefault().log(e);      

+    }

+    return result;

+  }  

+  

+  /**

+   * Clean pattern template structure.

+   * @param javaProject_p

+   * @param descriptor_p

+   */  

+  public static void cleanGeneratedStructures(IJavaProject javaProject_p, IDescriptor descriptor_p) {

+    if (javaProject_p == null || descriptor_p == null) {

+      return;

+    }

+    // Process only Workspace Plugin

+    IPluginModelBase model = PluginRegistry.findModel(javaProject_p.getProject());

+    if (model == null) {

+      return;

+    }

+    // Retrieve needed informations from IDescriptor

+    String patternShortId = (String) descriptor_p.getValue(ExtensionPointHelper.ATT_ID);

+    String patternTemplatePath = (String) descriptor_p.getValue(IPatternTemplateConstants.PATTERN_TEMPLATE_ATT_PATH);

+    String patternTemplateClass = (String) descriptor_p.getValue(IPatternTemplateConstants.PATTERN_TEMPLATE_ATT_CLASS);    

+    // Clean templates if any (this value is mandatory, but who knows...)

+    if (patternTemplatePath != null && patternTemplatePath.trim().length() > 0) {

+      FileHelper.deleteResource(

+        TemplateHelper.getTemplateRootIFolder(javaProject_p),

+        FileHelper.getPlatformResource(new Path(patternTemplatePath)),

+        true

+      );      

+    }

+    // Clean template resulting class if necessary (this value is optional)    

+    if (patternTemplateClass != null && patternTemplateClass.trim().length() > 0) {

+      JavaHelper.deleteJavaClass(

+        javaProject_p, 

+        new Path(FileHelper.convertPackageNameToFolderPath(patternTemplateClass)).addFileExtension(IPatternConstants.JAVA_SOURCE_FILE_EXTENSION), 

+        true

+      );

+    }

+    // Suppress generated pattern extension if any (this value is mandatory, but who knows...)

+    if (patternShortId != null && patternShortId.trim().length() > 0) {

+      IPluginChangesCommandRunner pluginChangesCommandRunner = EgfPdeActivator.getDefault().getPluginChangesCommandRunner();    

+      pluginChangesCommandRunner.performChangesOnPlugin(

+        model.getBundleDescription().getSymbolicName(), 

+        Collections.singletonList(

+          PatternTemplateExtensionFactory.unsetPatternTemplateExtension(patternShortId)

+        )

+      );

+    }

+  }

+

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/TemplateType.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/TemplateType.java
new file mode 100644
index 0000000..64264d8
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/TemplateType.java
@@ -0,0 +1,80 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.production;

+

+/**

+ * Defines an enumeration to list all available template engines.

+ * @author Guillaume Brocard

+ */

+public enum TemplateType {

+  

+  /**

+   * ACCELEO template engine.

+   */

+  ACCELEO("ACCELEO", "acceleo"), //$NON-NLS-1$ //$NON-NLS-2$  

+  

+  /**

+   * JET template engine.

+   */

+  JET("JET", "jet"), //$NON-NLS-1$ //$NON-NLS-2$

+  

+  /**

+   * JET2 template engine.

+   */

+  JET2("JET2", "jet2"), //$NON-NLS-1$ //$NON-NLS-2$   

+  

+  /**

+   * VELOCITY template engine.

+   */

+  VELOCITY("VELOCITY", "velocity"), //$NON-NLS-1$ //$NON-NLS-2$  

+

+  /**

+   * XPAND template engine.

+   */

+  XPAND("XPAND", "xpand"); //$NON-NLS-1$ //$NON-NLS-2$    

+  

+  /**

+   * Simple description.

+   */

+  private String _description;

+

+  /**

+   * Identifier.

+   */

+  private String _id;

+

+  /**

+   * Constructor.

+   * @param description_p

+   * @param id_p

+   */

+  private TemplateType(String description_p, String id_p) {

+    _description = description_p;

+    _id = id_p;

+  }

+

+  /**

+   * Get the description of this enumeration.

+   * @return the description

+   */

+  public String getDescription() {

+    return _description;

+  }

+

+  /**

+   * Get the identifier of this enumeration.

+   * @return the id

+   */

+  public String getId() {

+    return _id;

+  }

+  

+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/jet/IGenerator.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/jet/IGenerator.java
new file mode 100644
index 0000000..df87c68
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/jet/IGenerator.java
@@ -0,0 +1,27 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.production.jet;

+

+/**

+ * Default jet produced template skeleton.<br>

+ * Note that the argument name is unchanged due to EMF compatibility issues.

+ * @author Guillaume Brocard

+ */

+public interface IGenerator {

+  

+  /**

+   * Apply template generation, and get result as a {@link String}.

+   * @param argument

+   * @return

+   */

+  public String generate(Object argument);

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/jet/JETConstants.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/jet/JETConstants.java
new file mode 100644
index 0000000..7df83f5
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/jet/JETConstants.java
@@ -0,0 +1,28 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.production.jet;

+

+/**

+ * Patterns JET specific constants.

+ * @author Guillaume Brocard

+ */

+public interface JETConstants {

+  /**

+   * Start mark-up.

+   */

+  public static final String JET_MARKUP_START = "<%"; //$NON-NLS-1$

+  public static final String EXTERNAL_USE_JET_MARKUP_START = JETConstants.class.getName() + ".JET_MARKUP_START"; //$NON-NLS-1$

+  /**

+   * End mark-up.

+   */

+  public static final String JET_MARKUP_END = "%>"; //$NON-NLS-1$

+  public static final String EXTERNAL_USE_JET_MARKUP_END = JETConstants.class.getName() + ".JET_MARKUP_END"; //$NON-NLS-1$

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/messages.properties b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/messages.properties
new file mode 100644
index 0000000..5c6d323
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/messages.properties
@@ -0,0 +1,18 @@
+##

+#  Copyright (c) 2009 Thales Corporate Services S.A.S.

+#  All rights reserved. This program and the accompanying materials

+#  are made available under the terms of the Eclipse Public License v1.0

+#  which accompanies this distribution, and is available at

+#  http://www.eclipse.org/legal/epl-v10.html

+# 

+#  Contributors:

+#      Thales Corporate Services S.A.S - initial API and implementation

+##

+

+PatternProducer_ProgressReporting_GetPath=Resolving path for ''{0}''

+PatternProducer_PatternProductionErrorTitle=Pattern generation error

+PatternProducer_ProgressReporting_Title=Producing patterns 

+PatternProducer_ProgressReporting_PatternToJava=Generating pattern classes for ''{0}''

+PatternProducer_ProgressReporting_JavaToResult=Compiling resulting template for ''{0}''

+

+PatternTemplateProducer_PatternProductionErrorMessage=Error while generating pattern ''{0}''

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/template/TemplateHelper.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/template/TemplateHelper.java
new file mode 100644
index 0000000..51c6eba
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/production/template/TemplateHelper.java
@@ -0,0 +1,335 @@
+/**

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ */

+package org.eclipse.egf.pattern.production.template;

+

+import org.eclipse.core.resources.IFolder;

+import org.eclipse.core.resources.IResource;

+import org.eclipse.core.resources.ResourcesPlugin;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.jdt.core.IJavaProject;

+

+import org.eclipse.egf.common.constant.ICommonConstants;

+import org.eclipse.egf.common.helper.FileHelper;

+import org.eclipse.egf.common.misc.Couple;

+import org.eclipse.egf.common.misc.PlatformLocationType;

+import org.eclipse.egf.model.edit.helper.FactoryComponentHelper;

+import org.eclipse.egf.pattern.ecore.PatternConstants;

+import org.eclipse.egf.pattern.ecore.PatternHandler.PatternData;

+

+

+/**

+ * @author Guillaume Brocard

+ */

+public class TemplateHelper {

+    

+  /**

+   * Generated templates relative root path.

+   */

+  public static final String TEMPLATES_ROOT_PATH = "/templates/"; //$NON-NLS-1$

+  

+  /**

+   * Generated templates relative root IPath.

+   */

+  public static final IPath TEMPLATES_ROOT_IPATH = new Path("templates"); //$NON-NLS-1$  

+  

+  /**

+   * Generated templates relative path.

+   */

+  protected static final String GENERATED_TEMPLATES_PATH = TEMPLATES_ROOT_PATH + "generated/"; //$NON-NLS-1$

+  

+  /**

+   * Generated templates relative IPath.

+   */

+  protected static final IPath GENERATED_TEMPLATES_IPATH = TEMPLATES_ROOT_IPATH.append("generated"); //$NON-NLS-1$  

+  

+  /**

+   * Get generated template root IFolder for given project.<br>

+   * @param javaProject_p

+   * @return

+   */

+  public static IFolder getTemplateRootIFolder(IJavaProject javaProject_p) {

+    // Check

+    if (javaProject_p == null) {

+      return null;

+    }

+    // Find template root path member

+    IResource resource = ResourcesPlugin

+      .getWorkspace()

+      .getRoot()

+      .findMember(

+        javaProject_p

+        .getPath()

+        .append(TEMPLATES_ROOT_IPATH)

+      );

+    if (resource != null && resource instanceof IFolder) {

+      return (IFolder) resource;

+    }

+    return null;    

+  }

+  

+  /**

+   * Get generated template IFolder for given project.<br>

+   * @param javaProject_p

+   * @return

+   */

+  public static IFolder getGeneratedTemplateIFolder(IJavaProject javaProject_p) {

+    // Check

+    if (javaProject_p == null) {

+      return null;

+    }

+    // Find template generated path member

+    IResource resource = ResourcesPlugin

+      .getWorkspace()

+      .getRoot()

+      .findMember(

+        javaProject_p

+        .getPath()

+        .append(GENERATED_TEMPLATES_IPATH)

+      );

+    if (resource != null && resource instanceof IFolder) {

+      return (IFolder) resource;

+    }

+    return null;    

+  }

+  

+  /**

+   * Get generated template IFolder for given pattern short id.<br>

+   * @param javaProject_p

+   * @param patternShortId_p

+   * @return

+   */

+  public static IFolder getGeneratedPatternTemplateIFolder(IJavaProject javaProject_p, String patternShortId_p) {

+    // Check

+    if (javaProject_p == null || patternShortId_p == null) {

+      return null;

+    }

+    IFolder folder = getGeneratedTemplateIFolder(javaProject_p);

+    if (folder == null) {

+      return null;

+    }

+    IResource resource = folder.findMember(patternShortId_p);

+    if (resource != null && resource instanceof IFolder) {

+      return (IFolder) resource;

+    }

+    return null;    

+  }    

+

+  /**

+   * Get generated template file path for given pattern data.<br>

+   * Only usable for in-development patterns.<br>

+   * Deployed patterns templates should be dealt with differently.<br>

+   * TODO Guillaume Write a unique helper method that can deal with both cases.

+   * @param patternData_p

+   * @return

+   */

+  public static String getPatternTemplatePath(PatternData patternData_p) {

+    String result = null;

+    // Precondition.

+    if (patternData_p == null) {

+      return result;

+    }

+    // Get overriding template path.

+    String templatePath = patternData_p.getProductionOptionsHandler().getPatternTemplatePath();

+    if (templatePath != null && templatePath.trim().length() > 0) { // Use given template file path.

+      // Location is local to the java project hosting the pattern.

+      IPath patternTemplatePath = patternData_p.getJavaProject().getPath();

+      patternTemplatePath = patternTemplatePath.append(TEMPLATES_ROOT_PATH).append(templatePath);

+      result = patternTemplatePath.toString();

+    } else { // Use default template file construction.

+      result = computeTemplatePath(

+        patternData_p.getPluginId(), 

+        GENERATED_TEMPLATES_PATH, 

+        patternData_p.getPattern().getShortId()

+      );

+    }

+    return result;

+  }

+

+  /**

+   * Read template file.

+   * @param templateRelativePath_p the template relative path, prefixed by the factory component id.

+   * @return

+   */

+  public static String readTemplateFile(String templateRelativePath_p) {

+    String result = ICommonConstants.EMPTY_STRING;

+    // Precondition.

+    if (templateRelativePath_p == null) {

+      return result;

+    }

+    // Get plug-in id.

+    String fcId = new Path(templateRelativePath_p).segment(0);

+    String pluginId = FactoryComponentHelper.getPluginId(fcId, PlatformLocationType.WORKSPACE_THEN_TARGET_PLATFORM);

+    // Compatibility issue with the old way (v1.0.1) of referencing the templates.

+    if (pluginId == null) {

+      pluginId = fcId;

+    }

+    // Recompute physical path.

+    String physicalTemplateRelativePath = getPhysicalRelativePath(templateRelativePath_p, pluginId);

+    // Then read file at this relative path.

+    return FileHelper.readFile(physicalTemplateRelativePath);

+  }

+

+  /**

+   * Get physical relative path from logical one.

+   * @param logicalRelativePath_p

+   * @return

+   */

+  public static String getPhysicalRelativePath(String logicalRelativePath_p) {

+    String result = null;

+    if (logicalRelativePath_p == null) {

+      return result;

+    }

+    // Get plug-in id.

+    String fcId = new Path(logicalRelativePath_p).segment(0);

+    String pluginId = FactoryComponentHelper.getPluginId(fcId, PlatformLocationType.WORKSPACE_THEN_TARGET_PLATFORM);

+    // If plug-in id can not be resolved, then the logical path is not relative to an existing factory component.

+    // Try with first segment of the logical path directly (which is likely to be a plug-in id).

+    if (pluginId == null) {

+      pluginId = fcId;

+    }

+    // Then return physical relative path.

+    return getPhysicalRelativePath(logicalRelativePath_p, pluginId);

+  }

+

+  /**

+   * Get physical relative path from logical given one.

+   * @param logicalRelativePath_p

+   * @param pluginId_p

+   * @return

+   */

+  public static String getPhysicalRelativePath(String logicalRelativePath_p, String pluginId_p) {

+    String result = null;

+    if (logicalRelativePath_p == null || pluginId_p == null) {

+      return result;

+    }

+    // Exclude factory component id from logical relative path.

+    IPath relativePath = new Path(logicalRelativePath_p).removeFirstSegments(1);

+    // Then recompute relative path using the plug-in id as a prefix.

+    return 

+      new Path(pluginId_p + ICommonConstants.EMPTY_STRING)

+      .append(relativePath)

+      .toString();

+  }

+

+  /**

+   * Get template relative path for identified operation.

+   * @param patternShortId_p

+   * @param pluginId_p

+   * @param operationName_p

+   * @param operationId_p

+   * @return

+   */

+  public static String getTemplateRelativePath(String patternShortId_p, String pluginId_p, String operationName_p, String operationId_p) {

+    String result = null;

+    // Preconditions.

+    if (patternShortId_p == null || pluginId_p == null || operationName_p == null) {

+      return result;

+    }

+    // Unexpected entry. Generate method code does not point to a template but to other pattern methods.

+    if (PatternConstants.GENERATE_METHOD_NAME.equals(operationName_p)) {

+      return result;

+    }

+    Couple<String, String> folderNames = getTemplatesFolderNames(patternShortId_p);

+    String folderName = null;

+    // In case template is also generated, then add generated folder path before.

+    if (

+         PatternConstants.GENERATE_PRE_MATCHING_METHOD_NAME.equals(operationName_p)

+      || PatternConstants.GENERATE_POST_MATCHING_METHOD_NAME.equals(operationName_p)

+    ) {

+      folderName = folderNames.getValue();

+      // Compute correct relative path.

+      result = computeTemplatePath(pluginId_p, folderName, operationName_p);

+    } else if (operationId_p != null) { // By default, folder name is pattern one.

+      folderName = folderNames.getKey();

+      // Compute correct relative path.

+      result = computeTemplatePath(pluginId_p, folderName, operationId_p);

+    }

+    return result;

+  }

+

+  /**

+   * Get templates folder names from pattern name.

+   * @param patternShortId_p

+   * @return A couple of (User templates folder path (whatever the containing plug-in may be), Generated templates folder path (whatever the containing plug-in

+   *         may be)), null if given pattern name is.

+   */

+  private static Couple<String, String> getTemplatesFolderNames(String patternShortId_p) {

+    if (patternShortId_p == null) {

+      return null;

+    }

+    return 

+      new Couple<String, String>(

+        new StringBuilder(TEMPLATES_ROOT_PATH).append(patternShortId_p).toString(), 

+        new StringBuilder(GENERATED_TEMPLATES_PATH).append(patternShortId_p).toString()

+      );

+  }

+

+  /**

+   * Get templates folder relative paths.<br>

+   * @param patternShortId_p

+   * @param pluginId_p

+   * @return A couple of (User templates relative (to workspace) path, Generated templates relative (to workspace) path).

+   */

+  public static Couple<String, String> getPatternTemplatesFolderRelativePaths(String patternShortId_p, String pluginId_p) {

+    Couple<String, String> folderNames = getTemplatesFolderNames(patternShortId_p);

+    // Precondition.

+    if (folderNames == null) {

+      return null;

+    }

+    return 

+      new Couple<String, String>(

+        computeTemplateFolderPath(pluginId_p, folderNames.getKey()),

+        computeTemplateFolderPath(pluginId_p, folderNames.getValue())

+      );

+  }

+

+  /**

+   * Compute template file relative path from containing plugin id, containing folder path, and template file name.

+   * @param containingPluginId_p

+   * @param subFolderPath_p

+   * @param templateFileName_p

+   * @return

+   */

+  private static String computeTemplatePath(

+    String containingPluginId_p, 

+    String subFolderPath_p, 

+    String templateFileName_p

+  ) {

+    return 

+      new StringBuilder(

+        computeTemplateFolderPath(

+          containingPluginId_p, 

+          subFolderPath_p

+        )

+      )

+      .append(ICommonConstants.SLASH_CHARACTER)

+      .append(templateFileName_p)

+      .append(ICommonConstants.DOT_CHARACTER)

+      .append(PatternConstants.PATTERN_METHOD_FILE_EXTENSION)

+      .toString();

+  }

+

+  /**

+   * Compute template folder relative path from containing plugin id.

+   * @param containingPluginId_p

+   * @param subFolderPath_p

+   * @return

+   */

+  private static String computeTemplateFolderPath(String containingPluginId_p, String subFolderPath_p) {

+    return 

+      new StringBuilder(ICommonConstants.SLASH_CHARACTER)

+      .append(containingPluginId_p)

+      .append(subFolderPath_p)

+      .toString();

+  }

+  

+}

diff --git a/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/validation/PatternValidationHelper.java b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/validation/PatternValidationHelper.java
new file mode 100644
index 0000000..8a7bd2c
--- /dev/null
+++ b/plugins/org.eclipse.egf.pattern/src/org/eclipse/egf/pattern/validation/PatternValidationHelper.java
@@ -0,0 +1,59 @@
+/*******************************************************************************

+ *  Copyright (c) 2009 Thales Corporate Services S.A.S.

+ *  All rights reserved. This program and the accompanying materials

+ *  are made available under the terms of the Eclipse Public License v1.0

+ *  which accompanies this distribution, and is available at

+ *  http://www.eclipse.org/legal/epl-v10.html

+ * 

+ *  Contributors:

+ *      Thales Corporate Services S.A.S - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.egf.pattern.validation;

+

+import org.eclipse.egf.pattern.Pattern;

+import org.eclipse.emf.common.util.Diagnostic;

+import org.eclipse.emf.common.util.DiagnosticChain;

+import org.eclipse.emf.ecore.util.Diagnostician;

+

+

+/**

+ * @author Guillaume Brocard

+ */

+public class PatternValidationHelper {

+  /**

+   * Validate given pattern.

+   * @param pattern_p

+   * @param validationHandler_p A validation handler, that allows the creation of a specific parent diagnostic in case of an error.<br>

+   * <code>null</code> if returned one is sufficient.<br>

+   * Note that this is only required if diagnostic is to be shown in a user dialog, default diagnostic message might then seem too confusing.

+   * @return

+   */

+  public static Diagnostic validatePattern(Pattern pattern_p, IValidationHandler validationHandler_p) {

+    // Validate the pattern model as a whole.

+    Diagnostician diagnostician = new Diagnostician();

+    // Invoke validation.

+    Diagnostic diagnostic = diagnostician.validate(pattern_p);

+    // If on error, try validation handler.

+    boolean validationError = (Diagnostic.ERROR == diagnostic.getSeverity());

+    if (validationError && (null != validationHandler_p)) {

+      // Create sub-diagnostic dedicated to the model validation.

+      DiagnosticChain validationDiagnostic = validationHandler_p.createErrorRootDiagnostic();

+      // Then attach all the validation diagnostic children.

+      validationDiagnostic.addAll(diagnostic);

+    }

+    return diagnostic;

+  }

+

+  /**

+   * Validation handler, that creates expected diagnostic structure for results.

+   * @author Guillaume Brocard

+   */

+  public interface IValidationHandler {

+    /**

+     * Create a root diagnostic error that contains all the validation error.<br>

+     * Allows to choose a different way of 

+     * @return

+     */

+    public abstract DiagnosticChain createErrorRootDiagnostic();

+  }

+}