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 org.eclipse.jdt.core.dom.*;
import sharpen.core.csharp.ast.CSMethodBase;
import sharpen.core.csharp.ast.CSNode;
import sharpen.core.csharp.ast.CSTypeDeclaration;
import sharpen.core.framework.ByRef;
import sharpen.xobotos.api.Filter;
import sharpen.xobotos.api.TemplateVisitor;
import sharpen.xobotos.api.TemplateVisitor.VisitMode;
import sharpen.xobotos.api.actions.AbstractAction;
import sharpen.xobotos.api.actions.ModifyType;
import sharpen.xobotos.api.bindings.TypeBinding;
import sharpen.xobotos.api.interop.NativeHandle;
import sharpen.xobotos.api.interop.NativeStruct;
import sharpen.xobotos.api.interop.NativeType;
import sharpen.xobotos.config.LocationFilter.Match;
import sharpen.xobotos.config.annotations.AttributeReference;
import java.util.ArrayList;
import java.util.List;
@XStreamAlias(value="type")
public class TypeTemplate extends MemberTemplate<TypeDeclaration, CSTypeDeclaration>
implements ITypeContainer, IMemberContainer {
@XStreamAsAttribute
@XStreamAlias("partial")
private boolean _partial;
@XStreamAsAttribute
@XStreamAlias("abstract")
private boolean _abstract;
@XStreamAsAttribute
@XStreamAlias("sealed")
private boolean _sealed;
@XStreamAsAttribute
@XStreamAlias("recursive")
private boolean _recursive;
@XStreamImplicit(itemFieldName="method")
private List<MethodTemplate> _methods;
@XStreamImplicit(itemFieldName="constructor")
private List<ConstructorTemplate> _ctors;
@XStreamImplicit(itemFieldName = "destructor")
private List<DestructorTemplate> _destructors;
@XStreamImplicit(itemFieldName="field")
private List<FieldTemplate> _fields;
@XStreamImplicit(itemFieldName="type")
private List<TypeTemplate> _types;
@XStreamImplicit(itemFieldName="enum")
private List<EnumTemplate> _enums;
@XStreamImplicit(itemFieldName = "anonymous-class")
private List<AnonymousClassTemplate> _anonymousClasses;
@XStreamImplicit(itemFieldName = "property")
private List<PropertyTemplate> _properties;
@XStreamImplicit(itemFieldName = "action")
private List<AbstractAction> _actions;
@XStreamImplicit(itemFieldName = "remove-members")
private List<Filter> _removeMembers;
@XStreamAlias("modify")
private ModifyType _modifyType;
@XStreamAlias("binding")
private TypeBinding _binding;
@XStreamAlias("native-type")
private NativeType _nativeType;
@XStreamOmitField
@AttributeReference("native-handle")
private NativeHandle _nativeHandle;
@XStreamAlias("native-struct")
private NativeStruct _nativeStruct;
@Override
public ModifyType getModificationAction() {
return _modifyType;
}
@XStreamOmitField
public final static TypeTemplate DEFAULT = new TypeTemplate();
@Override
public TypeTemplate getTypeTemplate() {
return this;
}
public List<MethodTemplate> getMethods() {
return unmodifiable(_methods);
}
public List<ConstructorTemplate> getConstructors() {
return unmodifiable(_ctors);
}
public List<DestructorTemplate> getDestructors() {
return unmodifiable(_destructors);
}
public List<FieldTemplate> getFields() {
return unmodifiable(_fields);
}
public List<TypeTemplate> getTypes() {
return unmodifiable(_types);
}
public List<AnonymousClassTemplate> getAnonymousClasses() {
return unmodifiable(_anonymousClasses);
}
public List<EnumTemplate> getEnums() {
return unmodifiable(_enums);
}
public List<PropertyTemplate> getProperties() {
return unmodifiable(_properties);
}
public boolean isPartial() {
return _partial;
}
public boolean isAbstract() {
return _abstract;
}
public boolean isSealed() {
return _sealed;
}
public List<AbstractAction> getActions() {
return unmodifiableOrEmpty(_actions);
}
@Override
public TypeBinding getBinding() {
return _binding;
}
public NativeType getNativeType() {
return _nativeType;
}
public NativeStruct getNativeStruct() {
return _nativeStruct;
}
public List<AbstractMemberTemplate<?, ?>> getAllTypes() {
List<AbstractMemberTemplate<?, ?>> list = new ArrayList<AbstractMemberTemplate<?, ?>>();
if (_types != null)
list.addAll(_types);
if (_enums != null)
list.addAll(_enums);
if (_anonymousClasses != null)
list.addAll(_anonymousClasses);
return unmodifiable(list);
}
public List<AbstractMemberTemplate<?, ?>> getAllMembers() {
List<AbstractMemberTemplate<?, ?>> list = new ArrayList<AbstractMemberTemplate<?, ?>>();
if (_types != null)
list.addAll(_types);
if (_enums != null)
list.addAll(_enums);
if (_anonymousClasses != null)
list.addAll(_anonymousClasses);
if (_ctors != null)
list.addAll(_ctors);
if (_methods != null)
list.addAll(_methods);
if (_destructors != null)
list.addAll(_destructors);
if (_fields != null)
list.addAll(_fields);
if (_properties != null)
list.addAll(_properties);
return unmodifiable(list);
}
public boolean removeMember(ASTNode node) {
if (_removeMembers == null)
return false;
for (final Filter filter : _removeMembers) {
Match match = filter.matches(node);
if (match == Match.NEGATIVE)
return false;
else if (match == Match.POSITIVE)
return true;
}
return false;
}
public boolean visit(TemplateVisitor visitor, ASTNode member, Class<?> templateType) {
if (member instanceof TypeDeclaration)
return visit(visitor, getTypes(), (TypeDeclaration) member);
else if (member instanceof EnumDeclaration)
return visit(visitor, getEnums(), (EnumDeclaration) member);
else if (member instanceof AnonymousClassDeclaration)
return visit(visitor, getAnonymousClasses(), (AnonymousClassDeclaration) member);
else if (member instanceof FieldDeclaration)
return visit(visitor, getFields(), (FieldDeclaration) member);
else if (member instanceof MethodDeclaration) {
MethodDeclaration method = (MethodDeclaration) member;
if ((templateType != null) && templateType.equals(PropertyTemplate.class))
return visit(visitor, getProperties(), method);
if (method.isConstructor())
return visit(visitor, getConstructors(), method);
else if (Filter.isDestructor(method))
return visit(visitor, getDestructors(), method);
else
return visit(visitor, getMethods(), method);
}
return false;
}
public <T extends ASTNode, U extends CSNode, V extends AbstractMemberTemplate<T, U>> V findMemberTemplate(
final T node, final V defaultValue, final Class<V> klass) {
if (node instanceof AnonymousClassDeclaration) {
;
} else if (node.getParent() instanceof AnonymousClassDeclaration) {
;
} else if (!(node.getParent() instanceof TypeDeclaration))
return null;
final ByRef<V> result = new ByRef<V>();
TemplateVisitor visitor = new TemplateVisitor() {
@Override
public void accept(AbstractTemplate template) {
result.value = klass.cast(template);
}
};
if (!visit(visitor, node, klass))
return null;
return result.value != null ? result.value : defaultValue;
}
@Override
public TypeTemplate findTypeTemplate(final TypeDeclaration node) {
return findMemberTemplate(node, _recursive ? this : DEFAULT, TypeTemplate.class);
}
@Override
public EnumTemplate findEnumTemplate(final EnumDeclaration node) {
return findMemberTemplate(node, EnumTemplate.DEFAULT, EnumTemplate.class);
}
@Override
public AbstractMethodTemplate<? extends CSMethodBase> findMethodTemplate(MethodDeclaration node) {
if (node.isConstructor())
return findMemberTemplate(node, ConstructorTemplate.DEFAULT, ConstructorTemplate.class);
else if (Filter.isDestructor(node))
return findMemberTemplate(node, DestructorTemplate.DEFAULT, DestructorTemplate.class);
else
return findMemberTemplate(node, MethodTemplate.DEFAULT, MethodTemplate.class);
}
@Override
public FieldTemplate findFieldTemplate(FieldDeclaration node) {
return findMemberTemplate(node, FieldTemplate.DEFAULT, FieldTemplate.class);
}
public PropertyTemplate findPropertyTemplate(MethodDeclaration node) {
return findMemberTemplate(node, PropertyTemplate.DEFAULT, PropertyTemplate.class);
}
@Override
public AnonymousClassTemplate findAnonymousClassTemplate(AnonymousClassDeclaration node) {
return findMemberTemplate(node, AnonymousClassTemplate.DEFAULT, AnonymousClassTemplate.class);
}
public CSTypeDeclaration createCustomType(TypeDeclaration node) {
return null;
}
@Override
public void visit(TemplateVisitor visitor, VisitMode mode) {
super.visit(visitor, mode);
List<AbstractMemberTemplate<?, ?>> list;
if (mode == VisitMode.AllTypes)
list = getAllTypes();
else
list = getAllMembers();
for (final AbstractMemberTemplate<?, ?> template : list)
template.visit(visitor, mode);
}
public boolean isMainType() {
return false;
}
public NativeHandle getNativeHandle() {
return _nativeHandle;
}
}