/**
* Copyright 2002-2017 Evgeny Gryaznov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.textmapper.lapg.builder;
import org.textmapper.lapg.api.DerivedSourceElement;
import org.textmapper.lapg.api.SourceElement;
import org.textmapper.lapg.api.ast.AstClass;
import org.textmapper.lapg.api.ast.AstClassifier;
import org.textmapper.lapg.api.ast.AstField;
import org.textmapper.lapg.api.ast.AstType;
import java.util.*;
class LiAstClass extends LiUserDataHolder implements AstClass, DerivedSourceElement {
private final String name;
private final boolean isInterface;
private final AstClass container;
private final SourceElement origin;
private final List<AstField> fields = new ArrayList<>();
private final List<AstClassifier> inner = new ArrayList<>();
private final Set<AstClass> superClasses = new LinkedHashSet<>();
public LiAstClass(String name, boolean isInterface, AstClass container, SourceElement origin) {
this.name = name;
this.isInterface = isInterface;
this.container = container;
this.origin = origin;
}
@Override
public String getName() {
return name;
}
@Override
public AstClass getContainingClass() {
return container;
}
@Override
public boolean isInterface() {
return isInterface;
}
@Override
public AstClass[] getSuper() {
return superClasses.toArray(new AstClass[superClasses.size()]);
}
void addSuper(AstClass cl) {
if (isInterface && !(cl.isInterface())) {
throw new IllegalArgumentException("interfaces cannot extend classes");
}
superClasses.add(cl);
}
@Override
public AstField[] getFields() {
return fields.toArray(new AstField[fields.size()]);
}
void addField(AstField field) {
fields.add(field);
}
@Override
public AstClassifier[] getInner() {
return inner.toArray(new AstClassifier[inner.size()]);
}
void addInner(AstClassifier cl) {
inner.add(cl);
}
@Override
public SourceElement getOrigin() {
return origin;
}
@Override
public boolean isSubtypeOf(AstType another) {
if (another == AstType.ANY) return true;
if (!(another instanceof AstClass)) return false;
AstClass cl = (AstClass) another;
if (this == cl) return true;
LinkedList<AstClass> queue = new LinkedList<>();
Set<AstClass> seen = new HashSet<>();
queue.addAll(Arrays.asList(getSuper()));
seen.addAll(queue);
seen.add(this);
AstClass next;
while ((next = queue.poll()) != null) {
if (cl == next) {
return true;
}
for (AstClass s : next.getSuper()) {
if (seen.add(s)) {
queue.add(s);
}
}
}
return false;
}
@Override
public String toString() {
return name;
}
}