package sharpen.xobotos.api; import static sharpen.core.framework.Environments.my; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamImplicit; import com.thoughtworks.xstream.annotations.XStreamOmitField; import org.eclipse.jdt.core.ICompilationUnit; import sharpen.core.Configuration; import sharpen.core.csharp.ast.CSNode; import sharpen.core.csharp.ast.CSVisibility; import sharpen.core.framework.ByRef; import sharpen.core.framework.CompilationUnitPair; import sharpen.xobotos.api.TemplateVisitor.VisitMode; import sharpen.xobotos.api.bindings.BindingManager; import sharpen.xobotos.api.bindings.IBindingProvider; import sharpen.xobotos.api.templates.AbstractTemplate; import sharpen.xobotos.api.templates.CompilationUnitTemplate; import sharpen.xobotos.api.templates.NamespaceTemplate; import sharpen.xobotos.api.templates.TypeTemplate; import sharpen.xobotos.config.annotations.ReadIncludeFile; import sharpen.xobotos.config.annotations.ReferenceProvider; import sharpen.xobotos.config.annotations.RootContextReference; import sharpen.xobotos.config.xstream.IConfigurationFile; import sharpen.xobotos.config.xstream.RootContext; import sharpen.xobotos.generator.CompilationUnitBuilder; import sharpen.xobotos.output.IOutputProvider; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.List; @ReferenceProvider @RootContextReference("_rootContext") @XStreamAlias(value="api-definition") public class APIDefinition extends AbstractReference implements IConfigurationFile { @XStreamOmitField private RootContext<APIDefinition> _rootContext; @XStreamImplicit(itemFieldName="namespace") private List<NamespaceTemplate> _namespaces; @SuppressWarnings("unused") @XStreamImplicit(itemFieldName="templates") private List<TemplateSection> _templates; @XStreamImplicit(itemFieldName = "include-file") private List<IncludeFile> _includeFiles; public Configuration getConfiguration() { return my(Configuration.class); } public URI getProjectRoot() { return _rootContext.getProjectRoot(); } public List<NamespaceTemplate> getNamespaces() { List<NamespaceTemplate> list = new ArrayList<NamespaceTemplate>(); if (_includeFiles != null) { for (final IncludeFile file : _includeFiles) { list.addAll(file.getContents().getNamespaces()); } } if (_namespaces != null) list.addAll(_namespaces); return Collections.unmodifiableList(list); } public String getUnitName(ICompilationUnit unit) { String packageName = unit.getParent().getElementName(); String unitName = unit.getElementName().split("\\.")[0]; if (packageName.length() > 0) unitName = my(Configuration.class).applyNamespaceMappings(packageName) + '.' + unitName; return unitName; } public CompilationUnitTemplate findCompilationUnitTemplate(CompilationUnitPair pair) { final String fullName = getUnitName(pair.source); final ByRef<CompilationUnitTemplate> result = new ByRef<CompilationUnitTemplate>(null); TemplateVisitor visitor = new TemplateVisitor() { @Override public void accept(CompilationUnitTemplate template) { result.value = template; } }; for (final NamespaceTemplate def : getNamespaces()) { if (def.visit(visitor, fullName, VisitMode.FirstMatch)) break; } return result.value; } public boolean compilationUnitDefinesBindings(String unitName) { final ByRef<Boolean> result = new ByRef<Boolean>(false); TemplateVisitor visitor = new TemplateVisitor() { @Override public void accept(AbstractTemplate template) { if (template instanceof IBindingProvider) { IBindingProvider provider = (IBindingProvider) template; if (provider.getBinding() != null) result.value = true; } if (template instanceof TypeTemplate) { TypeTemplate type = (TypeTemplate) template; if (type.getNativeType() != null) result.value = true; else if (type.getNativeStruct() != null) result.value = true; } } }; for (final NamespaceTemplate def : getNamespaces()) { def.visit(visitor, unitName, VisitMode.All); } return result.value; } public CompilationUnitBuilder preprocess(CompilationUnitPair pair) { final String fullName = getUnitName(pair.source); final ByRef<IOutputProvider> defaultOutput = new ByRef<IOutputProvider>(null); final ByRef<CompilationUnitTemplate> unitTemplate = new ByRef<CompilationUnitTemplate>( CompilationUnitTemplate.DEFAULT); TemplateVisitor visitor = new TemplateVisitor() { @Override public void accept(NamespaceTemplate template) { if (defaultOutput.value != null) return; if (template.getOutputType() != null) defaultOutput.value = template; } @Override public void accept(CompilationUnitTemplate template) { unitTemplate.value = template; } }; for (final NamespaceTemplate def : getNamespaces()) { if (def.visit(visitor, fullName, VisitMode.FirstMatch)) break; } return my(BindingManager.class).preprocess(pair, unitTemplate.value, fullName, defaultOutput.value); } public static <T extends CSNode> List<T> cloneList(Iterable<T> nodes) { ArrayList<T> list = new ArrayList<T> (); for (T node : nodes) list.add(node); return list; } public static CSVisibility mapVisibility(Visibility visibility) { switch (visibility) { case PUBLIC: return CSVisibility.Public; case PROTECTED: return CSVisibility.Protected; case PRIVATE: return CSVisibility.Private; case PROTECTED_INTERNAL: return CSVisibility.ProtectedInternal; default: return CSVisibility.Internal; } } @ReadIncludeFile(contentsField = "_contents", fileNameField = "_fileName", fileType = APIDefinition.class) public static final class IncludeFile { @XStreamAsAttribute @XStreamAlias("file") @SuppressWarnings("unused") private String _fileName; @XStreamOmitField private APIDefinition _contents; public APIDefinition getContents() { return _contents; } } }