package sharpen.xobotos.api.templates; 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 sharpen.xobotos.api.TemplateSection; import sharpen.xobotos.api.TemplateVisitor; import sharpen.xobotos.api.TemplateVisitor.VisitMode; import sharpen.xobotos.config.LocationFilter.Match; import sharpen.xobotos.config.annotations.AttributeReference; import sharpen.xobotos.config.annotations.ReadIncludeFile; import sharpen.xobotos.output.IOutputProvider; import sharpen.xobotos.output.OutputType; import java.util.ArrayList; import java.util.List; @XStreamAlias(value="namespace") public class NamespaceTemplate extends AbstractLocationTemplate implements IOutputProvider { @XStreamOmitField public final static NamespaceTemplate DEFAULT = new NamespaceTemplate(); @XStreamImplicit(itemFieldName="namespace") private List<NamespaceTemplate> _namespaces; @XStreamImplicit(itemFieldName="compilation-unit") private List<CompilationUnitTemplate> _compilationUnits; @XStreamImplicit(itemFieldName = "include-file") private List<IncludeFile> _includeFiles; @XStreamImplicit(itemFieldName = "template-include-file") private List<TemplateIncludeFile> _templateIncludeFiles; @XStreamAsAttribute @XStreamAlias("recursive") private boolean _recursive; @XStreamOmitField @AttributeReference("output") private OutputType _outputType; @SuppressWarnings("unused") @XStreamImplicit(itemFieldName = "templates") private List<TemplateSection> _templates; public List<NamespaceTemplate> getNamespaces() { List<NamespaceTemplate> list = null; if (_templateIncludeFiles != null) { for (final TemplateIncludeFile file : _templateIncludeFiles) { NamespaceTemplateSection nsts = file.getContents(); List<NamespaceTemplate> ns = nsts.getNamespaces(); if (ns != null) { if (list == null) list = new ArrayList<NamespaceTemplate>(); list.addAll(ns); } } } if (_namespaces != null) { if (list == null) list = new ArrayList<NamespaceTemplate>(); list.addAll(_namespaces); } return unmodifiable(list); } public List<CompilationUnitTemplate> getCompilationUnits() { List<CompilationUnitTemplate> list = null; if (_includeFiles != null) { list = new ArrayList<CompilationUnitTemplate>(); for (final IncludeFile file : _includeFiles) { list.add(file.getContents()); } } if (_templateIncludeFiles != null) { for (final TemplateIncludeFile file : _templateIncludeFiles) { NamespaceTemplateSection nsts = file.getContents(); List<CompilationUnitTemplate> units = nsts.getCompilationUnits(); if (units != null) { if (list == null) list = new ArrayList<CompilationUnitTemplate>(); list.addAll(units); } } } if (_compilationUnits != null) { if (list == null) list = new ArrayList<CompilationUnitTemplate>(); list.addAll(_compilationUnits); } return unmodifiable(list); } @Override protected Object readResolve() { if (_namespaces == null) _namespaces = new ArrayList<NamespaceTemplate> (); return super.readResolve(); } public boolean isRoot() { return getName() == null && !hasLocationFilters(); } public boolean isRecursive() { return _recursive; } @Override public OutputType getOutputType() { return _outputType; } private static String buildName(String[] elements, int start, int end) { StringBuilder sb = new StringBuilder(); for (int i = start; i <= end; i++) { if (i > start) sb.append('.'); sb.append(elements[i]); } return sb.toString(); } public boolean visit(TemplateVisitor visitor, String name, VisitMode mode) { final String[] elements = name.split("\\."); String part = ""; String rest = name; boolean found = false; if (!isRoot()) { for (int i = 0; i < elements.length - 1; i++) { part = buildName(elements, 0, i); rest = buildName(elements, i + 1, elements.length - 1); Match match = matches(part); if (match == Match.NO_MATCH) continue; else if (match == Match.NEGATIVE) return false; found = true; break; } if (!found) return false; } else { Match match = matches(name); if (match != Match.POSITIVE) return false; } found = false; if (isRoot() || isRecursive() || (rest.indexOf('.') < 0)) { List<CompilationUnitTemplate> unitList = getCompilationUnits(); if (unitList != null) { for (final CompilationUnitTemplate template : unitList) { Match match = template.matches(rest); if (match == Match.NO_MATCH) continue; else if (match == Match.NEGATIVE) return false; template.visit(visitor, mode); found = true; if (mode == VisitMode.FirstMatch) break; } } else { found = true; } if (isRoot() && !found) { return false; } if (!isRecursive() && (mode == VisitMode.FirstMatch)) { visitor.accept(this); return true; } } if (found && (mode == VisitMode.FirstMatch)) { visitor.accept(this); return true; } for (final NamespaceTemplate template : getNamespaces()) { if (!template.visit(visitor, rest, mode)) continue; found = true; if (mode == VisitMode.FirstMatch) break; } if (found) visitor.accept(this); return found; } @Override protected void print(StringBuilder sb) { if (_recursive) sb.append(":recursive"); if (_outputType != null) { sb.append(':'); sb.append(_outputType); } super.print(sb); } @ReadIncludeFile(contentsField = "_contents", fileNameField = "_fileName", fileType = CompilationUnitTemplate.class) public static final class IncludeFile { @XStreamAsAttribute @XStreamAlias("file") @SuppressWarnings("unused") private String _fileName; @XStreamOmitField private CompilationUnitTemplate _contents; public CompilationUnitTemplate getContents() { return _contents; } } @ReadIncludeFile(contentsField = "_contents", fileNameField = "_fileName", fileType = NamespaceTemplateSection.class) public static final class TemplateIncludeFile { @XStreamAsAttribute @XStreamAlias("file") @SuppressWarnings("unused") private String _fileName; @XStreamOmitField private NamespaceTemplateSection _contents; public NamespaceTemplateSection getContents() { return _contents; } } }