/*******************************************************************************
* Copyright (c) 2005, 2009 committers of openArchitectureWare 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:
* committers of openArchitectureWare - initial API and implementation
*******************************************************************************/
package org.eclipse.internal.xpand2.ast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.internal.xpand2.model.XpandAdvice;
import org.eclipse.internal.xpand2.model.XpandDefinition;
import org.eclipse.internal.xpand2.model.XpandResource;
import org.eclipse.internal.xtend.expression.ast.Identifier;
import org.eclipse.internal.xtend.expression.ast.SyntaxElement;
import org.eclipse.internal.xtend.xtend.ast.ExtensionImportStatement;
import org.eclipse.xpand2.XpandExecutionContext;
import org.eclipse.xpand2.XpandUtil;
import org.eclipse.xtend.expression.AnalysationIssue;
/**
* *
*
* @author Sven Efftinge (http://www.efftinge.de) *
*/
public class Template extends SyntaxElement implements XpandResource {
private ImportDeclaration[] imports;
private Definition[] definitions;
private String fullyQualifiedName;
private ExtensionImportDeclaration[] extensions;
private Advice[] advices;
public ExtensionImportDeclaration[] getExtensions() {
return extensions;
}
public List<String> getImportedExtensionsAsList() {
final List<String> result = new ArrayList<String>(extensions.length);
for (ImportDeclaration ext : extensions) {
result.add(ext.getImportString().getValue());
}
return result;
}
public String getFullyQualifiedName() {
return fullyQualifiedName;
}
public void setFullyQualifiedName(final String fullyQualifiedName) {
this.fullyQualifiedName = fullyQualifiedName;
}
public Template(final ImportDeclaration[] imports, final ExtensionImportDeclaration[] extensions,
final Definition[] definitions, final Advice[] advices) {
this.imports = imports;
this.extensions = extensions;
for (int i = 0; i < definitions.length; i++) {
definitions[i].setOwner(this);
}
this.definitions = definitions;
for (int i = 0; i < advices.length; i++) {
advices[i].setOwner(this);
}
this.advices = advices;
}
public XpandDefinition[] getDefinitions() {
return definitions;
}
public List<XpandDefinition> getDefinitionsAsList() {
return Arrays.asList((XpandDefinition[]) definitions);
}
public AbstractDefinition[] getAllDefinitions() {
List<AbstractDefinition> l = new ArrayList<AbstractDefinition>();
l.addAll(Arrays.asList(definitions));
l.addAll(Arrays.asList(advices));
Collections.sort(l, new Comparator<SyntaxElement>() {
public int compare(SyntaxElement o1, SyntaxElement o2) {
return new Integer(o1.getStart()).compareTo(o2.getStart());
}
});
return l.toArray(new AbstractDefinition[l.size()]);
}
public ImportDeclaration[] getImports() {
return imports;
}
public List<ImportDeclaration> getImportsAsList() {
return Arrays.asList(imports);
}
private String[] commonPrefixes = null;
public void analyze(XpandExecutionContext ctx, final Set<AnalysationIssue> issues) {
try {
Set<AnalysationIssue> issuesFromThisResource = new HashSet<AnalysationIssue>();
ctx = (XpandExecutionContext) ctx.cloneWithResource(this);
if (ctx.getCallback() != null) {
if(!ctx.getCallback().pre(this, ctx)) {
return;
}
}
for (ExtensionImportDeclaration extension : extensions) {
extension.analyze(ctx, issuesFromThisResource);
}
checkDuplicateDefinitions(issuesFromThisResource);
//add error marker for duplicate extension imports
Set<Identifier> uniqueNames = new HashSet<Identifier>();
for (ExtensionImportDeclaration imp : extensions) {
if (uniqueNames.contains(imp.getImportString())) {
final String msg = "Duplicate extension importing: " + imp.getImportString();
issues.add(new AnalysationIssue(AnalysationIssue.SYNTAX_ERROR, msg, imp));
}
uniqueNames.add(imp.getImportString());
}
for (int i = 0; i < definitions.length; i++) {
definitions[i].analyze(ctx, issuesFromThisResource);
}
for (int i = 0; i < advices.length; i++) {
advices[i].analyze(ctx, issuesFromThisResource);
}
for (ImportDeclaration importDeclaration : imports) {
importDeclaration.analyze(ctx, issuesFromThisResource);
}
// filter all the 'Error parsing resource' issues that arised from a broken import
Set<AnalysationIssue> issuesToRemove = new HashSet<AnalysationIssue>();
for (AnalysationIssue issue : issuesFromThisResource) {
if (issue.getType().equals(AnalysationIssue.RESOURCE_NOT_FOUND)) {
ImportDeclaration importStmt = (ImportDeclaration) issue.getElement();
for (AnalysationIssue issue2 : issuesFromThisResource) {
if (issue2.getType().equals(AnalysationIssue.INTERNAL_ERROR) && issue2.getMessage().matches("Error parsing extensions.*"+importStmt.getImportString()+"$")) {
issuesToRemove.add(issue2);
}
}
}
}
issuesFromThisResource.removeAll(issuesToRemove);
issues.addAll(issuesFromThisResource);
} catch (RuntimeException ex) {
issues.add(new AnalysationIssue(AnalysationIssue.INTERNAL_ERROR, ex.getMessage(), this));
}
finally {
if (ctx.getCallback() != null) {
ctx.getCallback().post(this, ctx, null);
}
}
}
public XpandDefinition[] getDefinitionsByName(final String aName) {
final List<Definition> defs = new ArrayList<Definition>();
for (int i = 0; i < definitions.length; i++) {
final Definition def = definitions[i];
if (def.getName().equals(aName)) {
defs.add(def);
}
}
return defs.toArray(new XpandDefinition[defs.size()]);
}
public String[] getImportedNamespaces() {
if (commonPrefixes == null) {
final List<String> l = new ArrayList<String>();
final String thisNs = XpandUtil.withoutLastSegment(getFullyQualifiedName());
for (int i = 0; i < getImports().length; i++) {
final ImportDeclaration anImport = getImports()[i];
l.add(anImport.getImportString().getValue());
}
if (thisNs != null) {
l.add(thisNs);
}
commonPrefixes = l.toArray(new String[l.size()]);
}
return commonPrefixes;
}
public List<String> getImportedNamespacesAsList() {
return Arrays.asList(getImportedNamespaces());
}
String[] importedExtensions = null;
public String[] getImportedExtensions() {
if (importedExtensions == null) {
final List<String> l = new ArrayList<String>();
for (int i = 0; i < getExtensions().length; i++) {
final ImportDeclaration anImport = getExtensions()[i];
l.add(anImport.getImportString().getValue());
}
importedExtensions = l.toArray(new String[l.size()]);
}
return importedExtensions;
}
public XpandAdvice[] getAdvices() {
return advices;
}
private void checkDuplicateDefinitions(Set<AnalysationIssue> issues) {
Set<Definition> definitionSet = new HashSet<Definition>();
for (Definition def : definitions) {
if (!definitionSet.contains(def)) {
definitionSet.add(def);
}
else {
Definition origDef = null;
for (Iterator<Definition> it = definitionSet.iterator(); it.hasNext();) {
Definition d = it.next();
if (d.equals(def)) {
origDef = d;
break;
}
}
issues.add(new AnalysationIssue(AnalysationIssue.INTERNAL_ERROR, "Duplicate DEFINE definition '"
+ def.getName() + "'", def, false, def.getStart()));
issues.add(new AnalysationIssue(AnalysationIssue.INTERNAL_ERROR, "Duplicate DEFINE definition '"
+ (origDef!=null?origDef.getName():"") + "'", origDef, false, origDef.getStart()));
}
}
}
@Override
public String toString() {
return getFileName();
}
}