/*
Copyright (c) 2008 Arno Haase, Andr� Arnold.
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:
Arno Haase - initial API and implementation
Andr� Arnold
*/
package org.eclipse.xtend.middleend.xpand;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.internal.xpand2.ast.Advice;
import org.eclipse.internal.xpand2.ast.Template;
import org.eclipse.internal.xpand2.model.XpandAdvice;
import org.eclipse.internal.xpand2.model.XpandDefinition;
import org.eclipse.xpand2.XpandExecutionContext;
import org.eclipse.xpand2.XpandUtil;
import org.eclipse.xtend.backend.common.BackendTypesystem;
import org.eclipse.xtend.backend.common.NamedFunction;
import org.eclipse.xtend.middleend.MiddleEnd;
import org.eclipse.xtend.middleend.plugins.ImportedResource;
import org.eclipse.xtend.middleend.plugins.LanguageSpecificMiddleEnd;
import org.eclipse.xtend.middleend.plugins.ParsedResource;
import org.eclipse.xtend.middleend.xpand.internal.OldDefinitionConverter;
import org.eclipse.xtend.middleend.xpand.internal.xpandlib.XpandLibContributor;
import org.eclipse.xtend.middleend.xpand.plugin.XpandDefinitionName;
import org.eclipse.xtend.middleend.xtend.OldHelper;
import org.eclipse.xtend.middleend.xtend.internal.TypeToBackendType;
import org.eclipse.xtend.middleend.xtend.internal.xtendlib.XtendLibContributor;
/**
* This class manages the interdependent graph of parsed and converted Xpand files, allowing access to them by "compilation unit".
*
* @author Arno Haase (http://www.haase-consulting.com)
* @author Andr� Arnold
*/
public final class OldXpandRegistry implements LanguageSpecificMiddleEnd {
private static final Log _log = LogFactory.getLog (OldXpandRegistry.class);
private final XpandExecutionContext _ctx;
private BackendTypesystem _ts;
private MiddleEnd _middleEnd;
public OldXpandRegistry (Object specificData) {
if (specificData == null)
throw new IllegalArgumentException (getName() + " middle end is not initialized - will not contribute");
_ctx = (XpandExecutionContext) specificData;
}
public void setMiddleEnd (MiddleEnd middleEnd) {
_middleEnd = middleEnd;
_ts = middleEnd.getTypesystem();
}
public boolean canHandle (String xpandFile) {
xpandFile = OldHelper.normalizeXpandResourceName (xpandFile);
final String xpandResourceName = OldHelper.xpandFileAsOldResourceName (xpandFile);
try {
final Template file = (Template) _ctx.getResourceManager().loadResource (xpandResourceName, XpandUtil.TEMPLATE_EXTENSION);
return file != null;
}
catch (Exception exc) {
_log.debug("Xpand middleend can not handle file " + xpandFile, exc);
return false;
}
}
public boolean mayHandle (String resourceName) {
return resourceName.endsWith (XpandUtil.TEMPLATE_EXTENSION);
}
public String getName () {
return "Xpand";
}
public ParsedResource parseResource (String xpandFile) {
final ParsedResource result = new ParsedResource ();
xpandFile = OldHelper.normalizeXpandResourceName (xpandFile);
final String xpandResourceName = OldHelper.xpandFileAsOldResourceName (xpandFile);
final Template file = (Template) _ctx.getResourceManager().loadResource (xpandResourceName, XpandUtil.TEMPLATE_EXTENSION);
if (file == null)
throw new IllegalArgumentException ("could not find Xpand file '" + xpandResourceName + "'");
final XpandExecutionContext ctx = (XpandExecutionContext) _ctx.cloneWithResource (file);
final TypeToBackendType typeConverter = new TypeToBackendType (_ts, ctx);
final OldDefinitionConverter definitionFactory = new OldDefinitionConverter (ctx, typeConverter);
registerLibs (result);
final Set<XpandDefinitionName> referenced = new HashSet<XpandDefinitionName> ();
for (XpandDefinition ext: file.getDefinitions ())
result.getPublicFunctions().add (definitionFactory.createUnregistered (ext, referenced));
for (XpandAdvice a: file.getAdvices())
result.getAdvice().add (definitionFactory.create ((Advice) a, referenced));
// make sure all imported resources are registered as well
for (String imported: file.getImportedExtensions())
result.getImports().add (new ImportedResource (imported, false));
// collect all referenced template files...
final Set<String> xpandFileNames = new HashSet<String> ();
for (XpandDefinitionName n: referenced)
xpandFileNames.add (n.getCanonicalTemplateFileName());
for (String importedXpand: xpandFileNames)
result.getImports().add (new ImportedResource (importedXpand, false));
return result;
}
private void registerLibs(final ParsedResource result) {
// register the XtendLib. Do this first so the extension can override functions
XtendLibContributor xtendLibContrib = new XtendLibContributor (_middleEnd);
for (String contrib : xtendLibContrib.getContributingResources())
result.getImports().add (new ImportedResource (contrib, false));
for (NamedFunction f: xtendLibContrib.getContributedFunctions())
result.getPrivateFunctions().add (f);
// register the XpandLib
XpandLibContributor xpandLibContrib = new XpandLibContributor (_middleEnd);
for (String contrib : xpandLibContrib.getContributingResources())
result.getImports().add (new ImportedResource (contrib, false));
for (NamedFunction f: new XpandLibContributor (_middleEnd).getContributedFunctions())
result.getPrivateFunctions().add (f);
}
}