package com.ochafik.lang.jnaerator.parser; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.ochafik.lang.SyntaxUtils; public abstract class Identifier extends Element implements Comparable<Object> { public enum QualificationSeparator { Colons("::"), Dot("."); private QualificationSeparator(String s) { this.s = s; } private String s; @Override public String toString() { return s; } } public QualifiedIdentifier derive(QualificationSeparator separator, Identifier... subIdentifiers) { QualifiedIdentifier qi = new QualifiedIdentifier(separator); qi.add(this); for (Identifier i : subIdentifiers) if (i != null) qi.add(i); return qi; } public QualifiedIdentifier derive(QualificationSeparator separator, String... subIdentifiers) { QualifiedIdentifier qi = new QualifiedIdentifier(separator); qi.add(this); for (String i : subIdentifiers) qi.add(new SimpleIdentifier(i)); return qi; } @Override public Identifier clone() { return (Identifier)super.clone(); } public abstract boolean isPlain(); public abstract SimpleIdentifier resolveLastSimpleIdentifier(); public abstract List<SimpleIdentifier> resolveSimpleIdentifiers(); public abstract Identifier eraseTemplateArguments(); public static class SimpleIdentifier extends Identifier { private String name; private boolean javaStaticImportable; protected List<Expression> templateArguments = new ArrayList<Expression>(); public SimpleIdentifier() {} public SimpleIdentifier(String name, Expression... args) { setName(name); setTemplateArguments(Arrays.asList(args)); } public SimpleIdentifier setJavaStaticImportable(boolean javaStaticImportable) { this.javaStaticImportable = javaStaticImportable; return this; } public boolean isJavaStaticImportable() { return javaStaticImportable; } public void addTemplateArgument(Expression x) { if (x == null) return; x.setParentElement(this); templateArguments.add(x); } public Identifier eraseTemplateArguments() { return new SimpleIdentifier(getName()); } public List<Expression> getTemplateArguments() { return unmodifiableList(templateArguments); } public String getName() { return name; } public void setName(String name) { if (name != null && (name.contains(".") || name.contains("::"))) throw new IllegalArgumentException("Not a simple identifier : '" + name + "'"); this.name = name; } public void setTemplateArguments(List<Expression> templateArguments) { changeValue(this, this.templateArguments, templateArguments); } @Override public void accept(Visitor visitor) { visitor.visitSimpleIdentifier(this); } @Override public Element getNextChild(Element child) { return getNextSibling(templateArguments, child); } @Override public Element getPreviousChild(Element child) { return getPreviousSibling(templateArguments, child); } @Override public boolean replaceChild(Element child, Element by) { if (replaceChild(templateArguments, Expression.class, this, child, by)) { return true; } return super.replaceChild(child, by); } @Override public boolean isPlain() { return templateArguments.isEmpty(); } @Override public SimpleIdentifier resolveLastSimpleIdentifier() { return this; } @Override public List<SimpleIdentifier> resolveSimpleIdentifiers() { return Arrays.asList(this); } @Override public Identifier resolveAllButLastIdentifier() { return null; } } public static class QualifiedIdentifier extends Identifier { private List<SimpleIdentifier> identifiers = new ArrayList<SimpleIdentifier>(); private QualificationSeparator separator; public List<SimpleIdentifier> getIdentifiers() { return unmodifiableList(identifiers); } @Override public QualifiedIdentifier clone() { return (QualifiedIdentifier)super.clone(); } public void add(Identifier identifier) { if (identifier instanceof SimpleIdentifier) addIdentifier((SimpleIdentifier)identifier); else { QualifiedIdentifier oqi = (QualifiedIdentifier)identifier; if (!SyntaxUtils.equal(oqi.getSeparator(), separator)) throw new IllegalArgumentException("Attempting to derive qualified identifier " + this + " with mismatching separator " + separator + " and sub-name " + identifier); addIdentifiers(oqi.getIdentifiers()); } } public QualifiedIdentifier() {} public QualifiedIdentifier(QualificationSeparator separator) { setSeparator(separator); } public QualifiedIdentifier(QualificationSeparator separator, List<SimpleIdentifier> identifiers) { setSeparator(separator); setIdentifiers(identifiers); } public void setSeparator(QualificationSeparator separator) { this.separator = separator; } public QualificationSeparator getSeparator() { return separator; } public void setIdentifiers(List<SimpleIdentifier> identifiers) { changeValue(this, this.identifiers, identifiers); } @Override public void accept(Visitor visitor) { visitor.visitQualifiedIdentifier(this); } @Override public Element getNextChild(Element child) { return getNextSibling(identifiers, child); } @Override public Element getPreviousChild(Element child) { return getPreviousSibling(identifiers, child); } @Override public boolean replaceChild(Element child, Element by) { if (replaceChild(identifiers, SimpleIdentifier.class, this, child, by)) { return true; } return super.replaceChild(child, by); } public void addIdentifiers(List<SimpleIdentifier> is) { for (SimpleIdentifier i : is) addIdentifier(i); } public void addIdentifier(SimpleIdentifier i) { if (i == null) return; i.setParentElement(this); identifiers.add(i); } @Override public boolean isPlain() { return identifiers.size() == 1 && identifiers.get(0).isPlain(); } @Override public SimpleIdentifier resolveLastSimpleIdentifier() { return identifiers.isEmpty() ? null : identifiers.get(identifiers.size() - 1); } @Override public QualifiedIdentifier eraseTemplateArguments() { return resolveAllButLastIdentifier().derive(getSeparator(), resolveLastSimpleIdentifier().eraseTemplateArguments()); } @Override public List<SimpleIdentifier> resolveSimpleIdentifiers() { return getIdentifiers(); } @Override public Identifier resolveAllButLastIdentifier() { List<SimpleIdentifier> si = new ArrayList<SimpleIdentifier>(identifiers); if (!si.isEmpty()) { si.remove(si.size() - 1); } return new QualifiedIdentifier(getSeparator(), si); } } public final int compareTo(Object o) { String s = toString(); if (s == null) { return o == null ? 0 : -1; } String os = o == null ? null : String.valueOf(o); return os == null ? -1 : s.compareTo(os); } @Override public final boolean equals(Object obj) { return compareTo(obj) == 0; } @Override public final int hashCode() { return toString().hashCode(); } public abstract Identifier resolveAllButLastIdentifier(); }