blob: 72efea400addbbb6d6d95b5698ce30326898dd56 [file] [log] [blame]
/* *******************************************************************
* Copyright (c) 2010 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andy Clement
* Nieraj Singh
* ******************************************************************/
package org.aspectj.weaver.patterns;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Map;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.CompressingDataOutputStream;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
/**
* A TypeCategoryTypePattern matches on the category of a type, one of class/interface/aspect/inner/anonymous/enum/annotation, and
* these are specified in the pointcut via isClass() isInterface() isAspect() isInner() isAnonymous() isEnum() isAnnotation().
*
* @author Andy Clement
* @since 1.6.9
*/
public class TypeCategoryTypePattern extends TypePattern {
public static final int CLASS = 1;
public static final int INTERFACE = 2;
public static final int ASPECT = 3;
public static final int INNER = 4;
public static final int ANONYMOUS = 5;
public static final int ENUM = 6;
public static final int ANNOTATION = 7;
public static final int FINAL = 8;
private int category;
private int VERSION = 1;
public TypeCategoryTypePattern(int category) {
super(false);
this.category = category;
}
public int getTypeCategory() {
return category;
}
@Override
protected boolean matchesExactly(ResolvedType type) {
return isRightCategory(type);
}
@Override
protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
return isRightCategory(type);
}
@Override
public FuzzyBoolean matchesInstanceof(ResolvedType type) {
return FuzzyBoolean.fromBoolean(isRightCategory(type));
}
@Override
public TypePattern parameterizeWith(Map<String,UnresolvedType> typeVariableMap, World w) {
return this;
}
@Override
public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}
@Override
public boolean equals(Object other) {
if (!(other instanceof TypeCategoryTypePattern)) {
return false;
}
TypeCategoryTypePattern o = (TypeCategoryTypePattern) other;
return o.category == category;
}
// TODO is sourcelocation part of the identity or just a 'nice to have' - if important it should be in hashcode/equals
// TODO but if that is the case it needs addressing for all type patterns
@Override
public int hashCode() {
return category * 37;
}
@Override
public void write(CompressingDataOutputStream s) throws IOException {
s.writeByte(TypePattern.TYPE_CATEGORY);
s.writeInt(VERSION);
s.writeInt(category);
writeLocation(s);
}
@SuppressWarnings("unused")
public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
int version = s.readInt();
int category = s.readInt();
TypeCategoryTypePattern tp = new TypeCategoryTypePattern(category);
tp.readLocation(context, s);
return tp;
}
/**
* @return true if the supplied type is of the category specified for this type pattern
*/
private boolean isRightCategory(ResolvedType type) {
switch (category) {
case CLASS:
return type.isClass();
case INTERFACE:
return type.isInterface();
case ASPECT:
return type.isAspect();
case ANONYMOUS:
return type.isAnonymous();
case INNER:
return type.isNested();
case ENUM:
return type.isEnum();
case ANNOTATION:
return type.isAnnotation();
case FINAL:
return Modifier.isFinal(type.getModifiers());
}
return false;
}
}