/*******************************************************************************
 * Copyright (c) 2005-2015 Obeo and others
 *
 * 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:
 *    Obeo - initial API and implementation
 *    Thales - Add a preference to use specific scripts first
 *******************************************************************************/
package org.eclipse.sirius.query.legacy.gen.template.scripts;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.sirius.query.legacy.AcceleoInterpreterPlugin;
import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
import org.eclipse.sirius.query.legacy.gen.template.Template;
import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxExceptions;
import org.eclipse.sirius.query.legacy.gen.template.TemplateText;
import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallSetExpression;
import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalJavaService;
import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalModel;
import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.JavaServiceNotFoundException;
import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateFeatureStatement;
import org.eclipse.sirius.query.legacy.preferences.AcceleoPreferenceConstants;
import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoMetamodelProvider;
import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoModuleProvider;
import org.eclipse.sirius.query.legacy.tools.resources.Resources;
import org.eclipse.sirius.query.legacy.tools.strings.Int2;
import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
import org.osgi.framework.Bundle;

/**
 * Model specific generator configuration. A script file contains this
 * configuration. <li>isDefault() == false</li> <li>isSpecific() == true</li>
 * <li>hasFileTemplate() == true if more than one file template is defined in
 * the configuration</li> <li>isGenerated(EObject) == true if one file template
 * is defined for the object</li> <li>hasError(EObject) == false</li>
 * 
 * 
 */
public class SpecificScript extends AbstractScript {

    /**
     * Generator file extension.
     */
    public static final String GENERATORS_EXTENSION = "mt"; //$NON-NLS-1$

    /**
     * Should we profile the initialization of the script.
     */
    private boolean initProfiling = false;

    /**
     * Map of text templates.
     */
    protected Map textTemplates = new TreeMap(new Comparator() {
        public int compare(Object arg0, Object arg1) {
            if (arg0.equals(arg1)) {
                return 0;
            } else {
                ScriptDescriptor a0 = (ScriptDescriptor) arg0;
                ScriptDescriptor a1 = (ScriptDescriptor) arg1;
                int result = a0.type.compareTo(a1.type);
                if (result != 0) {
                    return result;
                } else {
                    return a0.name.compareTo(a1.name);
                }
            }
        }
    });

    /**
     * The name of the templates.
     */
    protected List textTemplateNames = new ArrayList();

    /**
     * Map of file templates.
     */
    protected Map fileTemplates = new HashMap();

    /**
     * Script file that contains the specific configuration.
     */
    protected File file;

    /**
     * Root element of the metamodel.
     */
    protected EPackage metamodel = null;

    /**
     * Gets the text template that corresponds to a file template.
     */
    protected Map file2TextTemplate = new HashMap();

    /**
     * Gets the file template that corresponds to a text template.
     */
    protected Map text2FileTemplate = new HashMap();

    /**
     * The chain file.
     */
    protected File chainFile = null;

    /**
     * The context of the script.
     */
    protected ISpecificScriptContext scriptContext = null;

    /**
     * The preference to use specific imports first
     */
    protected Boolean useSpecificImportsFirst = null;

    /**
     * Constructor.
     */
    public SpecificScript() {
        super();
        this.file = null;
        try {
            init(new ArrayList(), "", false); //$NON-NLS-1$
        } catch (final TemplateSyntaxExceptions e) {
            // Never catch
        }
    }

    /**
     * Constructor.
     * 
     * @param file
     *            is the script file that contains the specific configuration
     */
    public SpecificScript(File file) {
        this(file, null);
    }

    /**
     * Constructor.
     * 
     * @param file
     *            is the script file that contains the specific configuration
     * @param chainFile
     *            is the optional chain file
     */
    public SpecificScript(File file, File chainFile) {
        this();
        this.file = file;
        this.chainFile = chainFile;
        this.scriptContext = null;
    }

    /**
     * Constructor.
     * 
     * @param file
     *            is the script file that contains the specific configuration
     * @param chainFile
     *            is the optional chain file
     * @param scriptContext
     *            is the context of the script
     */
    public SpecificScript(File file, File chainFile, ISpecificScriptContext scriptContext) {
        this();
        this.file = file;
        this.chainFile = chainFile;
        this.scriptContext = scriptContext;
        if (scriptContext != null) {
            scriptContext.setScript(file, this);
        }
    }

    /**
     * @return the root element of the metamodel or null
     */
    public EPackage getMetamodel() {
        return metamodel;
    }

    /**
     * @return the map of text templates
     */
    public Map getTextTemplates() {
        return textTemplates;
    }

    /* (non-Javadoc) */
    @Override
    public File getFile() {
        return file;
    }

    /**
     * @return the chain file
     */
    public File getChainFile() {
        return chainFile;
    }

    /**
     * @param chainFile
     *            is the chain file
     */
    public void setChainFile(File chainFile) {
        this.chainFile = chainFile;
    }

    /* (non-Javadoc) */
    public boolean isDefault() {
        return false;
    }

    /* (non-Javadoc) */
    public boolean isSpecific() {
        return true;
    }

    /* (non-Javadoc) */
    public void reset() throws TemplateSyntaxExceptions {
        reset(new ArrayList());
    }

    /**
     * Returns whether specific imports will be loaded first.
     * @see org.eclipse.sirius.query.legacy.preferences.AcceleoPreferenceConstants.PREF_USE_SPECIFIC_SCRIPTS_FIRST
     */
    protected boolean useSpecificImportsFirst() {
      if (useSpecificImportsFirst == null) {
        useSpecificImportsFirst = Boolean.valueOf(Platform.getPreferencesService().getBoolean(AcceleoInterpreterPlugin.PLUGIN_ID, AcceleoPreferenceConstants.PREF_USE_SPECIFIC_SCRIPTS_FIRST, AcceleoPreferenceConstants.PREF_USE_SPECIFIC_SCRIPTS_FIRST_DEFAULT_VALUE, null));
      }
      return useSpecificImportsFirst.booleanValue();
    }

    private void reset(List fileHierarchy) throws TemplateSyntaxExceptions {
        if (file != null) {
            final String content = Resources.getFileContent(file).toString();
            reset(fileHierarchy, content);
        }
    }

    /**
     * Reset the generator.
     * 
     * @param content
     *            is the new content to be parsed
     * @throws TemplateSyntaxExceptions
     */
    public void reset(String content) throws TemplateSyntaxExceptions {
        reset(new ArrayList(), content);
    }

    /**
     * Reset the generator.
     * 
     * @param fileHierarchy
     *            is the imported scripts hierarchy
     * @param content
     *            is the new content to be parsed
     * @throws TemplateSyntaxExceptions
     */
    private synchronized void reset(List fileHierarchy, String content) throws TemplateSyntaxExceptions {
        if (file != null) {
            if (fileHierarchy.contains(file.getAbsolutePath())) {
                final List problems = new ArrayList();
                problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.RecursiveDependency"), this, 0)); //$NON-NLS-1$
                throw new TemplateSyntaxExceptions(problems);
            } else {
                fileHierarchy.add(file.getAbsolutePath());
            }
        }
        boolean checkOnly;
        if (oldContent == null || !oldContent.equals(content)) {
            oldContent = content;
            checkOnly = false;
            textTemplates.clear();
            textTemplateNames.clear();
            fileTemplates.clear();
            id2TextTemplate.clear();
            id2FileTemplate.clear();
            file2TextTemplate.clear();
            text2FileTemplate.clear();
            quickTemplates.clear();
        } else {
            checkOnly = true;
        }
        clearFoundProperties();
        current = null;
        init(fileHierarchy, content, checkOnly);

    }

    private String oldContent = null;

    /**
     * Gets the file template for the given text template.
     * 
     * @param textTemplate
     *            is a text template
     * @return the file template
     */
    public Template getFileTemplate(Template textTemplate) {
        return (Template) text2FileTemplate.get(textTemplate);

    }

    /**
     * Gets the text template for the given file template.
     * 
     * @param fileTemplate
     *            is a file template
     * @return the text template
     */
    public Template getTextTemplate(Template fileTemplate) {
        return (Template) file2TextTemplate.get(fileTemplate);
    }

    /* (non-Javadoc) */
    public Template getTextTemplateForEObject(EObject object, String name) throws FactoryException, ENodeException {
        return getTextTemplateForEClass(object.eClass(), name);
    }

    private Template getTextTemplateForEClass(EClass eClass, String name) throws FactoryException, ENodeException {
        Template template = getTextTemplateForEClassifier(eClass, name);
        if (template == null) {
            if (eClass.getESuperTypes().isEmpty() && eClass != EcorePackage.eINSTANCE.getEObject()) {
                /*
                 * We want to add an "artificial" specialization on EObject
                 */
                template = getTextTemplateForEClass(EcorePackage.eINSTANCE.getEObject(), name);
            }
            final Iterator superTypes = eClass.getESuperTypes().iterator();
            while (template == null && superTypes.hasNext()) {
                final EClassifier superType = (EClassifier) superTypes.next();
                if (superType instanceof EClass) {
                    template = getTextTemplateForEClass((EClass) superType, name);
                } else {
                    template = getTextTemplateForEClassifier(superType, name);
                }
            }
        }
        return template;
    }

    private Template getTextTemplateForEClassifier(EClassifier eClass, String name) throws FactoryException, ENodeException {
        final ScriptDescriptor key = new ScriptDescriptor(ETools.getEClassifierPath(eClass), name);
        Template template = (Template) id2TextTemplate.get(key);
        if (template == null) {
            template = (Template) textTemplates.get(key);
            if (template == null) {
                final Iterator it = textTemplates.entrySet().iterator();
                while (template == null && it.hasNext()) {
                    final Map.Entry entry = (Map.Entry) it.next();
                    if (name.equals(((ScriptDescriptor) entry.getKey()).name) && ('.' + key.type).endsWith('.' + ((ScriptDescriptor) entry.getKey()).type)) {
                        template = (Template) entry.getValue();
                    }
                }
            }
            if (template != null) {
                id2TextTemplate.put(key, template);
            }
        }
        return template;
    }

    /* (non-Javadoc) */
    public Template getRootTemplate(EObject object, boolean recursive) throws FactoryException, ENodeException {
        Template textTemplate = null;
        final Template fileTemplate = getFileTemplateForEObject(object);
        if (fileTemplate != null) {
            textTemplate = (Template) file2TextTemplate.get(fileTemplate);
        }
        if (recursive && !hasFileTemplate()) {
            if (textTemplate == null) {
                final Iterator imports = this.imports.iterator();
                while (textTemplate == null && imports.hasNext()) {
                    final IEvalSettings anImport = (IEvalSettings) imports.next();
                    if (anImport instanceof IScript) {
                        try {
                            textTemplate = ((IScript) anImport).getRootTemplate(object, false);
                        } catch (final ENodeException e) {
                            textTemplate = null;
                        }
                    }
                }
            }
        }
        if (textTemplate != null) {
            return textTemplate;
        } else {
            throw new ENodeException(AcceleoGenMessages.getString("ENodeError.UnresolvedRoot"), new Int2(0, 0), this, object, true); //$NON-NLS-1$
        }
    }

    /**
     * Gets the text template that corresponds to an identifiant.
     */
    protected Map id2TextTemplate = new HashMap();

    /**
     * Creates a new empty text template.
     * 
     * @param descriptor
     *            is the descriptor of the template
     * @return the new text template
     * @throws TemplateSyntaxException
     */
    public Template createTextTemplate(ScriptDescriptor descriptor) throws TemplateSyntaxException {
        return createTextTemplate(descriptor, "", new Int2(0, 0)); //$NON-NLS-1$
    }

    /**
     * Creates a new text template.
     * 
     * @param descriptor
     *            is the descriptor of the template
     * @param text
     *            is the content of the file
     * @param pos
     *            is the position of the template in the file
     * @return the new text template
     * @throws TemplateSyntaxException
     *             if the text has syntax errors
     */
    public Template createTextTemplate(ScriptDescriptor descriptor, String text, Int2 pos) throws TemplateSyntaxException {
        TemplateSyntaxException failure = null;
        Template template = (Template) textTemplates.get(descriptor);
        if (template == null) {
            // Template has been created before?
            final String quickEntry = descriptor.getType() + '\n' + descriptor.getName() + '\n' + text.substring(pos.b(), pos.e());
            template = (Template) quickTemplates.get(quickEntry);
            if (template == null) {
                // Create template
                try {
                    template = newTextTemplate(descriptor, text, pos);
                } catch (final TemplateSyntaxException e) {
                    template = newTextTemplate(descriptor, null, pos);
                    failure = e;
                }
                quickTemplates.put(quickEntry, template);
            }
            // Update the position of this template in the script file
            template.setPos(pos);
            textTemplates.put(descriptor, template);
            if (!textTemplateNames.contains(descriptor.getName())) {
                textTemplateNames.add(descriptor.getName());
            }
            current = template;
        } else {
            failure = new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateEntry.Text", new Object[] { descriptor.toString(), }), this, pos); //$NON-NLS-1$
        }
        if (failure != null) {
            throw failure;
        }
        return template;
    }

    private final Map quickTemplates = new HashMap();

    /**
     * It checks the syntax and creates a template for the given part of the
     * text. The part of the text to be parsed is delimited by the given limits.
     * 
     * @param descriptor
     *            is the descriptor of the template
     * @param text
     *            is the textual representation of the script that contains
     *            templates
     * @param pos
     *            delimits the part of the text to be parsed for this template
     * @return the new template
     * @throws TemplateSyntaxException
     */
    protected Template newTextTemplate(ScriptDescriptor descriptor, String text, Int2 pos) throws TemplateSyntaxException {
        final Template template = Template.read(text, pos, this);
        template.setDescriptor(descriptor);
        return template;
    }

    /**
     * Last template created.
     */
    protected Template current = null;

    /**
     * @return last template created
     */
    public Template getCurrent() {
        return current;
    }

    /**
     * @param current
     *            is the last template created
     */
    public void setCurrent(Template current) {
        this.current = current;
    }

    /* (non-Javadoc) */
    public boolean hasFileTemplate() {
        return fileTemplates.size() > 0;
    }

    /* (non-Javadoc) */
    public boolean isGenerated(EObject object) {
        try {
            return getFilePath(object, true) != null;
        } catch (final FactoryException e) {
            return false;
        }
    }

    /* (non-Javadoc) */
    public IPath getFilePath(EObject object, boolean recursive) throws FactoryException {
        if (hasFileTemplate()) {
            try {
                final Template fileTemplate = getFileTemplateForEObject(object);
                if (fileTemplate != null) {
                    final String path = fileTemplate.evaluateAsString(object, LaunchManager.create("run", false)).trim(); //$NON-NLS-1$
                    if (path.length() > 0) {
                        return new Path(path);
                    }
                }
            } catch (final ENodeException e) {
            }
        } else if (recursive) {
            final Iterator imports = this.imports.iterator();
            while (imports.hasNext()) {
                final IEvalSettings anImport = (IEvalSettings) imports.next();
                if (anImport instanceof IScript) {
                    final IPath path = ((IScript) anImport).getFilePath(object, false);
                    if (path != null) {
                        return path;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Gets the file template for the given object of the model.
     * 
     * @param object
     *            is an object of the model
     * @return the file template
     */
    public Template getFileTemplateForEObject(EObject object) {
        Template res = getFileTemplateForEClass(object.eClass());
        // try the default EObject type
        if (res == null) {
            res = getFileTemplateForEClass(EcorePackage.eINSTANCE.getEObject());
        }
        return res;

    }

    private Template getFileTemplateForEClass(EClass eClass) {
        Template template = getFileTemplateForEClassifier(eClass);
        if (template == null) {
            final Iterator superTypes = eClass.getESuperTypes().iterator();
            while (template == null && superTypes.hasNext()) {
                final EClassifier superType = (EClassifier) superTypes.next();
                if (superType instanceof EClass) {
                    template = getFileTemplateForEClass((EClass) superType);
                } else {
                    template = getFileTemplateForEClassifier(superType);
                }
            }
        }
        return template;
    }

    private Template getFileTemplateForEClassifier(EClassifier eClass) {
        final String typeID = ETools.getEClassifierPath(eClass);
        Template template = (Template) id2FileTemplate.get(typeID);
        if (template == null) {
            template = (Template) fileTemplates.get(typeID);
            if (template == null) {
                final Iterator it = fileTemplates.entrySet().iterator();
                while (template == null && it.hasNext()) {
                    final Map.Entry entry = (Map.Entry) it.next();
                    if (('.' + typeID).endsWith("." + entry.getKey())) { //$NON-NLS-1$
                        template = (Template) entry.getValue();
                    }
                }
            }
            if (template != null) {
                id2FileTemplate.put(typeID, template);
            }
        }
        return template;
    }

    /**
     * Gets the file template that corresponds to an identifiant.
     */
    protected Map id2FileTemplate = new HashMap();

    /**
     * Creates a new file template.
     * 
     * @param typeID
     *            is the identifiant
     * @param text
     *            is the content of the template
     * @param textTemplate
     *            is the text template that corresponds to the file template to
     *            be created
     * @throws TemplateSyntaxException
     */
    public void createFileTemplate(String typeID, String text, Template textTemplate) throws TemplateSyntaxException {
        createFileTemplate(typeID, text, new Int2(0, text.length()), textTemplate);
    }

    /**
     * Creates a new file template.
     * 
     * @param typeID
     *            is the identifiant
     * @param text
     *            is the content of the file
     * @param pos
     *            is the position of the template in the file
     * @param textTemplate
     *            is the text template that corresponds to the file template to
     *            be created
     * @throws TemplateSyntaxException
     */
    public void createFileTemplate(String typeID, String text, Int2 pos, Template textTemplate) throws TemplateSyntaxException {
        TemplateSyntaxException failure = null;
        Template template = (Template) fileTemplates.get(typeID);
        if (template == null) {
            try {
                template = Template.read(text, pos, this);
            } catch (final TemplateSyntaxException e) {
                template = new Template(this);
                failure = e;
            }
            fileTemplates.put(typeID, template);
            file2TextTemplate.put(template, textTemplate);
            text2FileTemplate.put(textTemplate, template);
        } else {
            failure = new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateEntry.File", new Object[] { typeID, }), this, pos); //$NON-NLS-1$
        }
        if (failure != null) {
            throw failure;
        }
    }

    /* (non-Javadoc) */
    @Override
    public String toString() {
        final StringBuffer buffer = new StringBuffer(super.toString());
        final Iterator it = textTemplates.entrySet().iterator();
        while (it.hasNext()) {
            final Map.Entry entry = (Map.Entry) it.next();
            final ScriptDescriptor key = (ScriptDescriptor) entry.getKey();
            buffer.append(TemplateConstants.SCRIPT_BEGIN); // TemplateConstants.
            // SCRIPT_BEGIN
            // ends with " "
            buffer.append(key.toString());
            // File template?
            final Template fileTemplate = (Template) fileTemplates.get(key.type);
            if (fileTemplate != null) {
                buffer.append(' ');
                buffer.append(TemplateConstants.SCRIPT_FILE);
                buffer.append(TemplateConstants.SCRIPT_PROPERTY_ASSIGN);
                buffer.append(TemplateConstants.LITERAL[0]);
                buffer.append(fileTemplate.toString());
                buffer.append(TemplateConstants.LITERAL[1]);
            }
            buffer.append(TemplateConstants.SCRIPT_END);
            buffer.append('\n');
            final String text = ((Template) entry.getValue()).toString();
            buffer.append(text);
            buffer.append("\n\n"); //$NON-NLS-1$
        }
        return buffer.toString();
    }

    /**
     * It checks the syntax and creates templates for the given text.
     * 
     * @param fileHierarchy
     *            is the imported scripts hierarchy
     * @param text
     *            is the text to be parsed
     * @param checkOnly
     *            indicates if it checks the syntax only
     * @throws TemplateSyntaxExceptions
     */
    protected void init(List fileHierarchy, String text, boolean checkOnly) throws TemplateSyntaxExceptions {
        final boolean isRoot = fileHierarchy.size() <= 1;
        if (AbstractScript.getScriptLoader() != null) {
            text = AbstractScript.getScriptLoader().load(text);
            if (text != null) {
                final List problems = new ArrayList();
                TemplateConstants.initConstants(text);
                oldImports = new ArrayList(imports);
                clearImports();
                if (text != null && text.length() > 0) {
                    // Get imports
                    if (file != null) {
                        try {
                            addImport(new EvalJavaService(file));
                        } catch (final JavaServiceNotFoundException e) {
                        }
                    }
                    parseImports(fileHierarchy, text, problems);
                    getSystemServicesFactory().addImports(this, isRoot);
                    // Parse scripts
                    if (!checkOnly) {
                        syntaxErrors.clear();
                        parseScripts(text, syntaxErrors);
                    }
                    problems.addAll(syntaxErrors);
                }
                // Check all expressions of the generator
                if (file != null) {
                    final IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath()));
                    if (workspaceFile != null && workspaceFile.exists()) {
                        if (isRoot) {
                            checkAllExpressions(problems);
                        }
                    }
                }
                // check only if the compilation result is not for runtime use
                if (scriptContext != null && scriptContext.getMaxLevel() != -1) {
                    checkOverride(problems);
                }
                // Throw TemplateSyntaxExceptions if problems are detected
                if (problems.size() > 0) {
                    throw new TemplateSyntaxExceptions(problems);
                }
            }
        }
    }

    /**
     * Check for masked overrides.
     * 
     * @param problems
     *            the problem list
     */
    private void checkOverride(List problems) {
        Map overrides = new HashMap();

        Iterator it = getImports().iterator();
        while (it.hasNext()) {
            Map localOverrides = new HashMap();
            IEvalSettings imp = (IEvalSettings) it.next();
            if (imp instanceof SpecificScript) {
                SpecificScript script = (SpecificScript) imp;
                final Iterator entries = script.textTemplates.entrySet().iterator();
                while (entries.hasNext()) {
                    final Map.Entry entry = (Map.Entry) entries.next();
                    final EClassifier type = ETools.getEClassifier(script.getMetamodel(), ((ScriptDescriptor) entry.getKey()).getType());
                    if (type instanceof EClass) {
                        final Template template = (Template) entry.getValue();
                        final String name = template.getDescriptor().getName();
                        List typeList = (List) overrides.get(name);
                        if (typeList == null) {
                            typeList = new ArrayList();
                            localOverrides.put(name, typeList);
                        } else {
                            if (isMaskedOverride((EClass) type, typeList)) {
                                TemplateSyntaxException problem = new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.BadOverride",
                                        new Object[] { fileScriptToImportString(script.getFile()), }), this, 1);
                                problem.setSeverity(IMarker.SEVERITY_WARNING);
                                problems.add(problem);
                            }
                        }
                        typeList.add(type);
                    }
                }
            }
            // merge localOverrides and overrides
            Iterator localIt = localOverrides.entrySet().iterator();
            while (localIt.hasNext()) {
                final Map.Entry entry = (Map.Entry) localIt.next();
                String name = (String) entry.getKey();
                List types = (List) overrides.get(name);
                if (types == null) {
                    overrides.put(name, entry.getValue());
                } else {
                    types.addAll((List) entry.getValue());
                }
            }
        }
    }

    private boolean isMaskedOverride(EClass type, List typeList) {
        boolean res = false;
        List supertypes = type.getEAllSuperTypes();
        Iterator it = typeList.iterator();
        while (!res && it.hasNext()) {
            res = supertypes.contains(it.next());
        }
        return res;
    }

    private final List syntaxErrors = new ArrayList();

    /**
     * It checks the syntax and creates the scripts for the given text.
     * 
     * @param text
     *            is the text to be parsed
     * @param problems
     *            are the syntax problems detected during this parsing
     */
    private void parseScripts(String text, List problems) {
        TemplateConstants.initConstants(text);
        ScriptDescriptor descriptor = null;
        Int2 end = new Int2(0, 0);
        while (end.e() > -1 && end.e() < text.length()) {
            final Int2 begin = TextSearch.getDefaultSearch().indexOf(text, TemplateConstants.SCRIPT_BEGIN, end.e(), null, TemplateConstants.INHIBS_SCRIPT_CONTENT);
            if (begin.b() > -1) {
                // Create a new script
                try {
                    newScript(descriptor, text, new Int2(end.e(), begin.b()));
                } catch (final TemplateSyntaxException e) {
                    problems.add(e);
                }
                // Clear informations
                descriptor = null;
                // Prepare new script
                end = TextSearch.getDefaultSearch().blockIndexEndOf(text, TemplateConstants.SCRIPT_BEGIN, TemplateConstants.SCRIPT_END, begin.b(), false, TemplateConstants.SPEC,
                        TemplateConstants.INHIBS_SCRIPT_DECLA);
                if (end.e() == -1) {
                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingScriptEndTag"), this, begin.b())); //$NON-NLS-1$
                } else {
                    try {
                        descriptor = getDescriptorFactory().createScriptDescriptor(text, this, new Int2(begin.e(), end.b()));
                    } catch (final TemplateSyntaxException e) {
                        problems.add(e);
                        descriptor = null;
                    }
                }
            } else { // -1
                // Create a new script
                try {
                    newScript(descriptor, text, new Int2(end.e(), text.length()));
                } catch (final TemplateSyntaxException e) {
                    problems.add(e);
                }
                end = new Int2(text.length(), text.length());
            }
        }
    }

    /**
     * Creates an instance of the descriptor factory. This new factory will be
     * used to create template's descriptors.
     * 
     * @return the new factory
     */
    protected ScriptDescriptorFactory createDescriptorFactory() {
        return new ScriptDescriptorFactory();
    }

    /**
     * Gets the instance of the descriptor factory. This factory is used to
     * create template's descriptors.
     * 
     * @return the descriptor factory
     */
    private ScriptDescriptorFactory getDescriptorFactory() {
        if (descriptorFactory == null) {
            descriptorFactory = createDescriptorFactory();
        }
        return descriptorFactory;
    }

    private ScriptDescriptorFactory descriptorFactory = null;

    /**
     * It checks the syntax and creates the imports for the given text.
     * 
     * @param fileHierarchy
     *            is the imported scripts hierarchy
     * @param text
     *            is the text to be parsed
     * @param problems
     *            are the syntax problems detected during this parsing
     */
    protected void parseImports(List fileHierarchy, String text, List problems) {
        metamodel = null;
        final List importValues = new ArrayList();
        int end = TextSearch.getDefaultSearch().indexOf(text, TemplateConstants.SCRIPT_BEGIN, 0, null, TemplateConstants.INHIBS_SCRIPT_CONTENT).b();
        if (end == -1) {
            end = text.length();
        }
        int pos = 0;
        while (pos > -1 && pos < end) {
            final Int2 bComment = TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.COMMENT_BEGIN, pos, end);
            final Int2 bImports = TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.IMPORT_BEGIN, pos, end);
            if (bComment.b() > -1 && (bImports.b() == -1 || bComment.b() <= bImports.b())) {
                final Int2 eComment = TextSearch.getDefaultSearch().blockIndexEndIn(text, TemplateConstants.COMMENT_BEGIN, TemplateConstants.COMMENT_END, bComment.b(), end, false);
                if (eComment.b() > -1) {
                    pos = eComment.e();
                } else {
                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingCommentEndTag"), this, bComment.b())); //$NON-NLS-1$
                    pos = end;
                }
            } else if (bImports.b() > -1) {
                final Int2 eImports = TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.IMPORT_END, bImports.e(), end);
                if (eImports.b() > -1) {
                    final Int2[] imports = TextSearch.getDefaultSearch().splitPositionsIn(text, bImports.e(), eImports.b(), new String[] { "\n" }, false); //$NON-NLS-1$
                    for (Int2 import1 : imports) {
                        Int2 importPos = import1;
                        importPos = TextSearch.getDefaultSearch().trim(text, importPos.b(), importPos.e());
                        if (importPos.b() > -1) {
                            if (importPos.e() > importPos.b()) {
                                if (TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.IMPORT_WORD, importPos.b(), importPos.e()).b() == importPos.b()) {
                                    final Int2 valuePos = TextSearch.getDefaultSearch().trim(text, importPos.b() + TemplateConstants.IMPORT_WORD.length(), importPos.e());
                                    if (valuePos.b() > -1) {
                                        final String value = text.substring(valuePos.b(), valuePos.e()).trim();
                                        if (importValues.contains(value)) {
                                            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateValue", new Object[] { "import", }), this, valuePos)); //$NON-NLS-1$ //$NON-NLS-2$
                                        } else {
                                            importValues.add(value);
                                            try {
                                                newImport(fileHierarchy, value, valuePos, importValues.size());
                                            } catch (final TemplateSyntaxException e) {
                                                problems.add(e);
                                            }
                                        }
                                    } else {
                                        problems.add(new TemplateSyntaxException(
                                                AcceleoGenMessages.getString("TemplateSyntaxError.EmptyImport"), this, importPos.b() + TemplateConstants.IMPORT_WORD.length())); //$NON-NLS-1$
                                    }
                                } else if (TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.MODELTYPE_WORD, importPos.b(), importPos.e()).b() == importPos.b()) {
                                    final Int2 valuePos = TextSearch.getDefaultSearch().trim(text, importPos.b() + TemplateConstants.MODELTYPE_WORD.length(), importPos.e());
                                    if (valuePos.b() > -1) {
                                        final String value = text.substring(valuePos.b(), valuePos.e()).trim();
                                        if (importValues.contains(value)) {
                                            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateValue", new Object[] { "metamodel", }), this, valuePos)); //$NON-NLS-1$ //$NON-NLS-2$
                                        } else {
                                            importValues.add(value);
                                            try {
                                                newImport(fileHierarchy, value, valuePos, importValues.size());
                                            } catch (final TemplateSyntaxException e) {
                                                problems.add(e);
                                            }
                                        }
                                    } else {
                                        problems.add(new TemplateSyntaxException(
                                                AcceleoGenMessages.getString("TemplateSyntaxError.EmptyValue", new Object[] { "metamodel", }), this, importPos.b() + TemplateConstants.MODELTYPE_WORD.length())); //$NON-NLS-1$ //$NON-NLS-2$
                                    }
                                } else {
                                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingKeyWord", new Object[] { "import", }), this, importPos.b())); //$NON-NLS-1$ //$NON-NLS-2$
                                }
                            }
                        }
                    }
                    pos = eImports.e();
                } else {
                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidImportSequence"), this, bImports.b())); //$NON-NLS-1$
                    pos = end;
                }
            } else {
                pos = end;
            }
        }
    }

    /**
     * Creates an import.
     * 
     * @param fileHierarchy
     *            is the imported scripts hierarchy
     * @param value
     *            is the import value
     * @param valuePos
     *            is the position of the value in the script
     * @param num
     *            is the number of the import
     * @throws TemplateSyntaxException
     */
    protected void newImport(List fileHierarchy, String value, Int2 valuePos, int num) throws TemplateSyntaxException {
        boolean isMetamodelImport = parseMetamodelImport(value, valuePos, num);
        if (scriptContext == null || scriptContext.getMaxLevel() == -1 || fileHierarchy.size() < scriptContext.getMaxLevel()) {
            if (!isMetamodelImport) {
                if (file != null) {
                    boolean service = false;
                    boolean specificExists = false;

                    if (useSpecificImportsFirst()) {
                        specificExists = newImportFromSpecificImports(fileHierarchy, value, valuePos, num);
                        service = newImportFromJavaServices(value);

                    } else {
                        service = newImportFromJavaServices(value);
                        if (!service) {
                          specificExists = newImportFromSpecificImports(fileHierarchy, value, valuePos, num);
                        }
                    }

                    if (!service && !specificExists) {
                        throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedImport", new Object[] { value, }), this, valuePos); //$NON-NLS-1$
                    }
                }
            }
        }
    }

    /**
     * Try to load the given class.
     * @return whether a class has been loaded
     */
    protected boolean newImportFromJavaServices(String qualifiedName) {

      boolean service = false;
      try {
          addImportForJavaService(file, qualifiedName);
          service = true;
      } catch (final JavaServiceNotFoundException e) {
          // throw new
          // TemplateSyntaxException(e.getMessage(),this,valuePos);
      }
      return service;
    }

    /**
     * Try to load specific imports for the given name
     * @return whether a specific script has been loaded
     */
    protected boolean newImportFromSpecificImports(List fileHierarchy, String value, Int2 valuePos, int num) throws TemplateSyntaxException {
      boolean specificExists = false;

      // Specific script file
      final String[] specificExtensions = getSpecificImportExtensions();
      for (String specificExtension : specificExtensions) {
          final File specificFile = resolveScriptFile(file, value, specificExtension);
          if ((specificFile != null) && specificFile.exists()) {
              // Is recursive import?
              IScript genSpecific = this;
              do {
                  if ((genSpecific.getFile() != null) && genSpecific.getFile().equals(specificFile)) {
                      throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.RecursiveImport"), this, valuePos); //$NON-NLS-1$
                  }
                  genSpecific = genSpecific.getSpecific();
              } while (genSpecific != null);
              // Add import
              try {
                  if (!tryOptimizedImport(fileHierarchy, specificFile)) {
                      final SpecificScript newImport = createSpecificImport(specificFile);
                      newImport.setInitProfiling(initProfiling);
                      newImport.reset(new ArrayList(fileHierarchy));
                      newImport.setSpecific(this);
                      addImport(newImport);
                  }
              } catch (final TemplateSyntaxExceptions e) {
                  String message = AcceleoGenMessages.getString("SpecificScript.ErroneousTemplate"); //$NON-NLS-1$
                  if (e.getProblems().size() == 1) {
                      message += " : " + ((TemplateSyntaxException) e.getProblems().get(0)).getMessage(); //$NON-NLS-1$
                  }
                  throw new TemplateSyntaxException(message, this, valuePos);
              }
              specificExists = true;
          }
      }
      return specificExists;
    }

    /**
     * Add a java service to import list.
     * 
     * @param file
     *            the current script file
     * @param value
     *            the class name
     * @throws JavaServiceNotFoundException
     *             if the class designed by value doesn't exists
     */
    protected void addImportForJavaService(final File file, final String value) throws JavaServiceNotFoundException {
        addImport(new EvalJavaService(file, value));
    }

    protected File resolveScriptFile(File script, String importValue, String extension) {

        File res = null;
        final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(script.getAbsolutePath()));
        if (file != null && file.isAccessible()) {
            final IPath importPath = new Path(importValue.replaceAll("\\.", "/")).addFileExtension(extension); //$NON-NLS-1$ //$NON-NLS-2$
            res = getScriptFileInProject(file.getProject(), importPath);
        } else {
            final String pluginId = AcceleoModuleProvider.getDefault().getPluginId(script);
            if (pluginId != null) {
                final Bundle bundle = Platform.getBundle(pluginId);
                if (bundle != null) {
                    res = AcceleoModuleProvider.getDefault().getFile(bundle.getSymbolicName(), importValue, extension);
                }
            }
        }

        return res;
    }

    private String fileScriptToImportString(File script) {
        String res = "";
        final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(script.getAbsolutePath()));
        String[] segments = file.getProjectRelativePath().segments();
        for (int i = 1; i < segments.length; ++i) {
            res += segments[i];
            if (i < segments.length - 1) {
                res += "."; //$NON-NLS-1$
            }
        }
        return res;
    }

    private File getScriptFileInProject(IProject project, IPath importPath) {
        File result = null;
        if (project.exists()) {
            try {
                final IJavaProject javaProject = JavaCore.create(project);
                final IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
                for (int i = 0; i < entries.length && result == null; i++) {
                    final IClasspathEntry entry = entries[i];
                    if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE && entry.getPath().segmentCount() > 1) {
                        final IFile test = ResourcesPlugin.getWorkspace().getRoot().getFile(entry.getPath().append(importPath));
                        if (test.exists()) {
                            result = test.getLocation().toFile();
                        }
                    }
                }
                for (int i = 0; i < entries.length && result == null; i++) {
                    final IClasspathEntry entry = entries[i];
                    if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT && entry.getPath().segmentCount() == 1) {
                        final IProject entryProject = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().segment(0));
                        if (entryProject != null && entryProject.exists()) {
                            result = getScriptFileInProject(entryProject, importPath);
                        }
                    }
                }
            } catch (final JavaModelException e) {
                result = null;
            }
            if (result == null) {
                final String[] requiredPluginIDs = Resources.getRequiredPluginIDs(project);
                for (int i = 0; i < requiredPluginIDs.length && result == null; i++) {
                    final IProject bundleProject = ResourcesPlugin.getWorkspace().getRoot().getProject(requiredPluginIDs[i]);
                    if (bundleProject != null && bundleProject.exists()) {
                        result = getScriptFileInProject(bundleProject, importPath);
                    } else if (Platform.getBundle(requiredPluginIDs[i]) != null) {
                        result = AcceleoModuleProvider.getDefault().getFile(requiredPluginIDs[i], importPath);
                    }
                }
            }
        }
        return result;
    }

    /**
     * Tries to parse the import value and creates a metamodel import.
     * 
     * @param value
     *            is the import value
     * @param valuePos
     *            is the position of the value in the script
     * @param num
     *            is the number of the import
     * @return true if a metamodel import has been created
     * @throws TemplateSyntaxException
     */
    protected boolean parseMetamodelImport(String value, Int2 valuePos, int num) throws TemplateSyntaxException {
        if (num == 1) {
            value = value.trim();
            final EPackage regValue = EPackage.Registry.INSTANCE.getEPackage(value);
            if (regValue != null) {
                final EvalModel anImport = new EvalModel(value);
                if (anImport.getMetamodel() == null) {
                    throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedMetamodel"), this, valuePos); //$NON-NLS-1$
                }
                metamodel = anImport.getMetamodel();
                addImport(anImport);
                return true;
            } else {
                IPath ecorePath = new Path(value);
                if (ecorePath.segmentCount() >= 2) {
                    ecorePath = ecorePath.removeFileExtension().addFileExtension("ecore"); //$NON-NLS-1$
                }
                final File ecoreFile = AcceleoMetamodelProvider.getDefault().getFile(ecorePath);
                if (ecoreFile != null && ecoreFile.exists()) {
                    final EvalModel anImport = new EvalModel(value);
                    if (anImport.getMetamodel() == null) {
                        throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedMetamodel"), this, valuePos); //$NON-NLS-1$
                    }
                    metamodel = anImport.getMetamodel();
                    addImport(anImport);
                    return true;
                } else {
                    throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedMetamodel"), this, valuePos); //$NON-NLS-1$
                }
            }
        } else {
            return false;
        }
    }

    /**
     * Gets all the file extensions that are accepted in the imports.
     * 
     * @return a table of extensions
     */
    protected String[] getSpecificImportExtensions() {
        return new String[] { SpecificScript.GENERATORS_EXTENSION };
    }

    /**
     * Creates a specific import for the given file.
     * 
     * @param specificFile
     *            is the file to import
     * @return the new specific import
     */
    protected SpecificScript createSpecificImport(File specificFile) {
        if (scriptContext != null) {
            final SpecificScript result = scriptContext.getScript(specificFile, chainFile);
            if (result != null) {
                return result;
            }
        }
        final SpecificScript result = new SpecificScript(specificFile, chainFile, scriptContext);
        return result;
    }

    /**
     * Tries a quick import with the file modification stamp.
     * 
     * @param fileHierarchy
     *            is the imported scripts hierarchy
     * @param file
     *            is the file to import
     * @return true if the quick import is done
     * @throws TemplateSyntaxExceptions
     */
    private boolean tryOptimizedImport(List fileHierarchy, File file) throws TemplateSyntaxExceptions {
        boolean tryOptimizedImport;
        final IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath()));
        if (workspaceFile != null && workspaceFile.isAccessible()) {
            final Double newModificationStamp = new Double(workspaceFile.getModificationStamp());
            final Double oldModificationStamp = (Double) mt2OldModificationStamp.get(workspaceFile);
            if (oldModificationStamp != null && oldModificationStamp.doubleValue() == newModificationStamp.doubleValue()) {
                tryOptimizedImport = true;
            } else {
                tryOptimizedImport = false;
            }
            mt2OldModificationStamp.put(workspaceFile, newModificationStamp);
        } else {
            tryOptimizedImport = true;
        }
        if (tryOptimizedImport) {
            final Iterator it = oldImports.iterator();
            while (it.hasNext()) {
                final Object oldImportObject = it.next();
                if (oldImportObject instanceof SpecificScript) {
                    final SpecificScript oldImport = (SpecificScript) oldImportObject;
                    if (oldImport.getFile().equals(file)) {
                        oldImport.clearFoundProperties();
                        oldImport.reset(new ArrayList(fileHierarchy));
                        addImport(oldImport);
                        oldImport.setSpecific(this);
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /* (non-Javadoc) */
    @Override
    public void addImport(IEvalSettings element) {
        super.addImport(element);
    }

    /**
     * Quick imports : old script modification stamp.
     */
    private final Map mt2OldModificationStamp = new HashMap();

    /**
     * Quick imports : old imports.
     */
    private List oldImports = new ArrayList();

    /**
     * It checks the semantic of the links.
     * 
     * @param problems
     *            are the semantic problems detected during this checking.
     */
    protected void checkAllExpressions(List problems) {

        if (metamodel == null) {
            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidImportSequence"), this, 0)); //$NON-NLS-1$
        } else {
            final Iterator textTemplates = this.textTemplates.entrySet().iterator();
            while (textTemplates.hasNext()) {
                final Map.Entry entry = (Map.Entry) textTemplates.next();
                final String type = ((ScriptDescriptor) entry.getKey()).type;
                final Template template = (Template) entry.getValue();
                checkAllExpressions(problems, type, template);
            }
            final Iterator fileTemplates = this.fileTemplates.entrySet().iterator();
            while (fileTemplates.hasNext()) {
                final Map.Entry entry = (Map.Entry) fileTemplates.next();
                final String type = (String) entry.getKey();
                final Template template = (Template) entry.getValue();
                checkAllExpressions(problems, type, template);
            }
        }

    }

    private void checkAllExpressions(List problems, String type, Template template) {
        // Get the EClassifier for the identifier
        final EClassifier classifier = ETools.getEClassifier(metamodel, type);
        if (classifier == null) {
            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedClassifier", new Object[] { type, }), this, template.getPos())); //$NON-NLS-1$
        } else {
            // Check the elements of the template
            final List allElements = template.getAllElements(TemplateCallSetExpression.class);
            if (template.getPostExpression() != null) {
                allElements.addAll(template.getPostExpression().getAllElements(TemplateCallSetExpression.class));
            }
            final Iterator elements = allElements.iterator();
            while (elements.hasNext()) {
                final TemplateCallSetExpression callSet = (TemplateCallSetExpression) elements.next();
                if (callSet != null) {
                    if (!callSet.isPredefined()) {
                        // Check not predefined links
                        Object resolvedType = callSet.getRootResolver(classifier, this);
                        final Iterator calls = callSet.iterator();
                        TemplateCallExpression call = null;
                        while (resolvedType != null && calls.hasNext()) {
                            // Remark : resolvedType == GENERIC_TYPE
                            // => resolvedType != null
                            call = (TemplateCallExpression) calls.next();
                            if (resolvedType == IEvalSettings.GENERIC_TYPE && call.getLink().length() > 0) {
                                final char[] array = call.getLink().toCharArray();
                                for (int i = 0; i < array.length; i++) {
                                    if (!Character.isJavaIdentifierPart(array[i])) {
                                        problems.add(new TemplateSyntaxException(
                                                AcceleoGenMessages.getString("TemplateSyntaxError.InvalidCharacter", new Object[] { Character.toString(array[i]), }), this, new Int2(call.getPos().b() + i, call.getPos().b() + i + 1))); //$NON-NLS-1$
                                    }
                                }
                            }
                            resolvedType = resolveType(resolvedType, call);
                        }
                        if (call != null) {
                            if (resolvedType == null) {
                                problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedCall", new Object[] { call, }), this, call.getPos())); //$NON-NLS-1$
                            }
                        }
                    } else {
                        // Check the user tags
                        if (callSet.getFirst().getLink().equals(TemplateConstants.USER_BEGIN_NAME) && callSet.getFirst().countArguments() == 0) {
                            // Remark : isPredefined() &&
                            // USER_BEGIN_NAME => getParent() is
                            // instance of TemplateFeatureStatement
                            final TemplateFeatureStatement feature = (TemplateFeatureStatement) callSet.getParent();
                            boolean valid = false;
                            if (feature.getNext() != null && feature.getNext() instanceof TemplateText) {
                                final String nextString = ((TemplateText) feature.getNext()).toString();
                                final int iNewLine = nextString.indexOf("\n"); //$NON-NLS-1$
                                if (iNewLine == -1 || nextString.substring(0, iNewLine).trim().length() > 0) {
                                    valid = true;
                                }
                            }
                            if (!valid && feature.getPrevious() != null && feature.getPrevious() instanceof TemplateText) {
                                final String previousString = ((TemplateText) feature.getPrevious()).toString();
                                final int iNewLine = previousString.lastIndexOf("\n"); //$NON-NLS-1$
                                if (iNewLine == -1 || previousString.substring(iNewLine).trim().length() > 0) {
                                    valid = true;
                                }
                            }
                            if (!valid) {
                                problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.EmptyUserTag"), this, callSet.getPos())); //$NON-NLS-1$
                            }
                        }
                    }
                }
            }
        }
    }

    private void newScript(ScriptDescriptor descriptor, String text, Int2 limitsTextTemplate) throws TemplateSyntaxException {
        if (descriptor != null && text != null) {
            limitsTextTemplate = Template.formatTemplate(text, limitsTextTemplate, 2);
            final Template textTemplate = createTextTemplate(descriptor, text, limitsTextTemplate);
            if (descriptor.getFileTemplate() != null) {
                createFileTemplate(descriptor.getType(), text, descriptor.getFileTemplate(), textTemplate);
            }
            if (descriptor.getPostExpression() != null) {
                final TemplateExpression postExpression = TemplateExpression.fromString(text, descriptor.getPostExpression(), this);
                textTemplate.setPostExpression(postExpression);
            }
        }
    }

    /* (non-Javadoc) */
    public boolean hasError(EObject object) {
        return false;
    }

    /* (non-Javadoc) */
    @Override
    public ENode eGetTemplate(ENode node, String name, ENode[] args, LaunchManager mode) throws ENodeException, FactoryException {

        return eGetTemplateSub(node, name, args, mode);
    }

    public ENode eGetTemplateSub(ENode node, String name, ENode[] args, LaunchManager mode) throws ENodeException, FactoryException {
        if (textTemplateNames.contains(name)) {
            if (node.isEObject()) {
                try {
                    final EObject object = node.getEObject();
                    final Template template = getTextTemplateForEObject(object, name);
                    if (template != null) {
                        contextPush(IScript.TEMPLATE_ARGS, args);
                        ENode result;
                        try {
                            final boolean withComment = !hasFileTemplate() && name.equals("write"); //$NON-NLS-1$
                            if (withComment) {
                                result = template.evaluateWithComment(object, mode);
                            } else {
                                result = template.evaluate(object, mode);
                            }
                            if (result.isNull()) {
                                final List children = template.getSignificantStatements();
                                if (children.size() > 1 || children.size() == 1 && !(children.get(0) instanceof TemplateFeatureStatement)) {
                                    // isNull() => ""
                                    result.asString();
                                }
                            }
                            if (withComment && name.equals("write") && template.isEmptyEvaluation()) { //$NON-NLS-1$
                                return null;
                            }
                        } finally {
                            contextPop(IScript.TEMPLATE_ARGS);
                        }
                        return result;
                    }
                } catch (final ENodeCastException e) {
                    // Never catch
                }
            }
        }
        return null;
    }

    /* (non-Javadoc) */
    @Override
    public Object resolveType(Object type, TemplateCallExpression call, int depth) {
        if ("".equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_SCRIPT.equals(call.getPrefix())) { //$NON-NLS-1$
            if (call.getLink().length() == 0) {
                return IEvalSettings.GENERIC_TYPE;
            }
            if (type instanceof EClassifier) {
                final Iterator textTemplates = this.textTemplates.entrySet().iterator();
                while (textTemplates.hasNext()) {
                    final Map.Entry entry = (Map.Entry) textTemplates.next();
                    final ScriptDescriptor key = (ScriptDescriptor) entry.getKey();
                    if (ETools.ofType((EClassifier) type, key.type) && key.name.equals(call.getLink())) {
                        return IEvalSettings.GENERIC_TYPE;
                    }
                }
            } else if (type == IEvalSettings.GENERIC_TYPE) {
                final Iterator textTemplates = this.textTemplates.entrySet().iterator();
                while (textTemplates.hasNext()) {
                    final Map.Entry entry = (Map.Entry) textTemplates.next();
                    final ScriptDescriptor key = (ScriptDescriptor) entry.getKey();
                    if (key.name.equals(call.getLink())) {
                        return IEvalSettings.GENERIC_TYPE;
                    }
                }
            }
        }
        return super.resolveType(type, call, depth);
    }

    /* (non-Javadoc) */
    @Override
    public Object[] getCompletionProposals(Object type, int depth) {
        final List result = new ArrayList();
        // Templates proposals
        if (type instanceof EClassifier) {
            final Iterator textTemplates = this.textTemplates.entrySet().iterator();
            while (textTemplates.hasNext()) {
                final Map.Entry entry = (Map.Entry) textTemplates.next();
                if (ETools.ofType((EClassifier) type, ((ScriptDescriptor) entry.getKey()).type)) {
                    result.add(entry);
                }
            }
        }
        // Other proposals
        result.addAll(Arrays.asList(super.getCompletionProposals(type, depth)));
        return result.toArray();
    }

    /**
     * Clears the found properties.
     */
    private void clearFoundProperties() {
        name2Properties.clear();
        allProperties = null;
    }

    /**
     * Gets the property for the key and the property file (without extension).
     * 
     * @param name
     *            is the name of the property file (without ".properties"
     *            extension)
     * @param key
     *            is the key
     * @return the value for the given key
     * @throws CoreException
     * @throws IOException
     */
    public String getProperty(String name, String key) throws CoreException, IOException {
        final Properties properties = getOrCreateProperties(name);
        if (properties != null) {
            return properties.getProperty(key);
        } else {
            return null;
        }
    }

    private Properties getOrCreateProperties(String name) throws CoreException, IOException {
        Properties properties = (Properties) name2Properties.get(name);
        if (properties == null) {
            boolean found = false;
            final List containers = getPropertyContainers();
            final Iterator it = containers.iterator();
            while (it.hasNext() && !found) {
                final File container = (File) it.next();
                if (container.exists() && container.isDirectory()) {
                    final File[] members = container.listFiles();
                    for (int i = 0; i < members.length && !found; i++) {
                        if (members[i].isFile() && (name + ".properties").equals(members[i].getName())) { //$NON-NLS-1$
                            properties = new Properties();
                            properties.load(members[i].toURL().openStream());
                            name2Properties.put(name, properties);
                            found = true;
                        }
                    }
                }
            }
        }
        return properties;
    }

    private final Map name2Properties = new HashMap();

    /**
     * Gets the value for the key in all the properties files.
     * 
     * @param key
     *            is the key
     * @return the value for the given key
     * @throws CoreException
     * @throws IOException
     */
    public String getProperty(String key) throws CoreException, IOException {
        final Properties[] properties = getOrCreateProperties();
        for (Properties propertie : properties) {
            if (propertie != null) {
                final String value = propertie.getProperty(key);
                if (value != null) {
                    return value;
                }
            }
        }
        return null;
    }

    private Properties[] getOrCreateProperties() throws CoreException, IOException {
        if (allProperties == null) {
            final List allPropertiesList = new ArrayList();
            final List containers = getPropertyContainers();
            final Iterator it = containers.iterator();
            while (it.hasNext()) {
                final File container = (File) it.next();
                if (container.exists() && container.isDirectory()) {
                    final File[] members = container.listFiles();
                    for (File member : members) {
                        if (member.isFile() && member.getName() != null && member.getName().endsWith(".properties")) { //$NON-NLS-1$
                            final Properties properties = new Properties();
                            properties.load(member.toURL().openStream());
                            name2Properties.put(new Path(member.getName()).removeFileExtension().lastSegment(), properties);
                            allPropertiesList.add(properties);
                        }
                    }
                }
            }
            allProperties = (Properties[]) allPropertiesList.toArray(new Properties[allPropertiesList.size()]);
        }
        return allProperties;
    }

    private Properties[] allProperties = null;

    /**
     * Gets the properties files containers.
     * 
     * @return the properties files containers
     */
    protected List getPropertyContainers() {
        final List result = new ArrayList();
        if (chainFile != null && chainFile.getParentFile() != null) {
            result.add(chainFile.getParentFile());
        }
        if (file != null && file.getParentFile() != null) {
            result.add(file.getParentFile());
            File project = null;
            final IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath()));
            if (workspaceFile != null && workspaceFile.isAccessible()) {
                project = workspaceFile.getProject().getLocation().toFile();
            }
            final String pluginId = AcceleoModuleProvider.getDefault().getPluginId(file);
            if (pluginId != null) {
                final Bundle bundle = Platform.getBundle(pluginId);
                if (bundle != null) {
                    final URL url = bundle.getEntry("/"); //$NON-NLS-1$
                    if (url != null) {
                        final File file = new File(Resources.transformToAbsolutePath(url));
                        if (file.exists()) {
                            project = file;
                        }
                    }
                }
            }
            if (project != null && project.exists()) {
                File parent = file.getParentFile().getParentFile();
                while (parent != null && parent.exists()) {
                    result.add(parent);
                    if (parent.equals(project)) {
                        break;
                    } else {
                        parent = parent.getParentFile();
                    }
                }
            }
        }
        return result;
    }

    /* (non-Javadoc) */
    public boolean validateCall(TemplateCallExpression call) {
        return "".equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_SCRIPT.equals(call.getPrefix()); //$NON-NLS-1$
    }

    /**
     * Sets initProfiling value.
     * 
     * @param initProfiling
     */
    public void setInitProfiling(boolean initProfiling) {
        this.initProfiling = initProfiling;
    }
}
