package org.develnext.jphp.core.tokenizer.token.stmt; import org.develnext.jphp.core.tokenizer.TokenMeta; import org.develnext.jphp.core.tokenizer.TokenType; import org.develnext.jphp.core.tokenizer.token.CommentToken; import org.develnext.jphp.core.tokenizer.token.expr.value.NameToken; import php.runtime.common.Modifier; import php.runtime.reflection.ClassEntity; import java.util.*; public class ClassStmtToken extends StmtToken { private Modifier modifier; private boolean isFinal; private boolean isAbstract; private NamespaceStmtToken namespace; private NameToken name; private CommentToken docComment; private ExtendsStmtToken extend; private ImplementsStmtToken implement; private MethodStmtToken constructor; private List<ConstStmtToken> constants; private List<ClassVarStmtToken> properties; private List<MethodStmtToken> methods; private List<NameToken> uses; private Map<String, List<Alias>> aliases; private Map<String, Replacement> replacements; private ClassEntity.Type classType = ClassEntity.Type.CLASS; protected ClassStmtToken(TokenMeta meta, TokenType type) { super(meta, type); properties = new ArrayList<ClassVarStmtToken>(); constants = new ArrayList<ConstStmtToken>(); methods = new ArrayList<MethodStmtToken>(); uses = new ArrayList<NameToken>(); } public ClassStmtToken(TokenMeta meta) { this(meta, TokenType.T_CLASS); } public boolean isInterface() { return classType == ClassEntity.Type.INTERFACE; } public void setInterface(boolean anInterface) { classType = anInterface ? ClassEntity.Type.INTERFACE : classType; } public boolean isTrait() { return classType == ClassEntity.Type.TRAIT; } public ClassEntity.Type getClassType() { return classType; } public void setClassType(ClassEntity.Type classType) { this.classType = classType; } public NameToken getName() { return name; } public void setName(NameToken name) { this.name = name; } public ExtendsStmtToken getExtend() { return extend; } public void setExtend(ExtendsStmtToken extend) { this.extend = extend; } public ImplementsStmtToken getImplement() { return implement; } public void setImplement(ImplementsStmtToken implement) { this.implement = implement; } public boolean isFinal() { return isFinal; } public void setFinal(boolean aFinal) { isFinal = aFinal; } public boolean isAbstract() { return isAbstract; } public void setAbstract(boolean anAbstract) { isAbstract = anAbstract; } public MethodStmtToken getConstructor() { return constructor; } public void setConstructor(MethodStmtToken constructor) { this.constructor = constructor; } public List<ConstStmtToken> getConstants() { return constants; } public void setConstants(List<ConstStmtToken> constants) { this.constants = constants; } public List<ClassVarStmtToken> getProperties() { return properties; } public void setProperties(List<ClassVarStmtToken> properties) { this.properties = properties; } public List<MethodStmtToken> getMethods() { return methods; } public void setMethods(List<MethodStmtToken> methods) { this.methods = methods; } public NamespaceStmtToken getNamespace() { return namespace; } public void setNamespace(NamespaceStmtToken namespace) { this.namespace = namespace; } public Modifier getModifier() { return modifier; } public void setModifier(Modifier modifier) { this.modifier = modifier; } public String getFulledName(char delimiter){ return namespace == null || namespace.getName() == null ? name.getName() : namespace.getName().toName(delimiter) + delimiter + name.getName(); } public String getFulledName(){ return getFulledName('\\'); } public List<NameToken> getUses() { return uses; } public void setUses(List<NameToken> uses) { this.uses = uses; } public void addAlias(String className, String methodName, Modifier modifier, String name) { if (aliases == null) aliases = new LinkedHashMap<String, List<Alias>>(); List<Alias> l = aliases.get(methodName); if (l == null) { aliases.put(methodName.toLowerCase(), l = new ArrayList<Alias>()); } l.add(new Alias(className, modifier, name)); } public List<Alias> findAliases(String methodName) { return aliases == null ? null : aliases.get(methodName.toLowerCase()); } public Map<String, List<Alias>> getAliases() { return aliases; } public Map<String, Replacement> getReplacements() { return replacements; } public boolean addReplacement(String className, String methodName, Set<String> classes) { if (classes == null || classes.isEmpty()) throw new IllegalArgumentException("classes must not be null or empty"); if (replacements == null) replacements = new LinkedHashMap<String, Replacement>(); Replacement replacement = replacements.get(methodName.toLowerCase()); if (replacement == null) { replacement = new Replacement(className, classes); replacements.put(methodName.toLowerCase(), replacement); return true; } else { for(String e : classes) { if (replacement.hasTrait(e)) return false; } replacement.addTraits(classes); return true; } } public Replacement findReplacement(String methodName) { return replacements == null ? null : replacements.get(methodName.toLowerCase()); } public CommentToken getDocComment() { return docComment; } public void setDocComment(CommentToken docComment) { this.docComment = docComment; } protected static class MethodName { protected final String className; protected final String name; public MethodName(String className, String name) { this.className = className; this.name = name; } public String getClassName() { return className; } public String getName() { return name; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof MethodName)) return false; MethodName that = (MethodName) o; return className.equalsIgnoreCase(that.className) && name.equalsIgnoreCase(that.name); } @Override public int hashCode() { int result = className.toLowerCase().hashCode(); result = 31 * result + name.toLowerCase().hashCode(); return result; } } public static class Replacement { private final String origin; private final Set<String> traitsLower; private final Set<String> traits; public Replacement(String origin, Set<String> traits) { this.origin = origin; this.traits = traits; traitsLower = new HashSet<String>(); for(String e : traits) traitsLower.add(e.toLowerCase()); } public boolean hasTrait(String name) { return traitsLower.contains(name.toLowerCase()); } public String getOrigin() { return origin; } public Set<String> getTraits() { return traits; } public void addTraits(Collection<String> list) { traits.addAll(list); for(String e : list) traitsLower.add(e.toLowerCase()); } } public static class Alias { protected final String trait; protected final Modifier modifier; protected final String name; public Alias(String trait, Modifier modifier, String name) { this.trait = trait; this.modifier = modifier; this.name = name; } public Modifier getModifier() { return modifier; } public String getName() { return name; } public String getTrait() { return trait; } } }