/* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). * 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: * PARC initial implementation * ******************************************************************/ package org.aspectj.weaver; import java.util.Map; import org.aspectj.bridge.ISourceLocation; import org.aspectj.util.PartialOrder; public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparable { protected ResolvedTypeMunger munger; protected ResolvedType aspectType; public ConcreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) { this.munger = munger; this.aspectType = aspectType; } /** * Equivalence can be true for an EclipseTypeMunger and a BcelTypeMunger that represent the same transformation (just at * different points in the pipeline). */ public boolean equivalentTo(Object other) { if (!(other instanceof ConcreteTypeMunger)) { return false; } ConcreteTypeMunger o = (ConcreteTypeMunger) other; ResolvedTypeMunger otherTypeMunger = o.getMunger(); ResolvedTypeMunger thisTypeMunger = getMunger(); if (thisTypeMunger instanceof NewConstructorTypeMunger && otherTypeMunger instanceof NewConstructorTypeMunger) { return (((NewConstructorTypeMunger) otherTypeMunger).equivalentTo(thisTypeMunger)) && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType())); } else { return ((otherTypeMunger == null) ? (thisTypeMunger == null) : otherTypeMunger.equals(thisTypeMunger)) && ((o.getAspectType() == null) ? (getAspectType() == null) : o.getAspectType().equals(getAspectType())); } } // public abstract boolean munge(LazyClassGen gen); /** * returns null for mungers that are used internally, but were not part of a declared thing in source code. */ public ResolvedTypeMunger getMunger() { return munger; } public ResolvedType getAspectType() { return aspectType; } public ResolvedMember getSignature() { return munger.getSignature(); } public World getWorld() { return aspectType.getWorld(); } public ISourceLocation getSourceLocation() { if (munger == null) { return null; } return munger.getSourceLocation(); // XXX } public boolean matches(ResolvedType onType) { if (munger == null) { throw new RuntimeException("huh: " + this); } return munger.matches(onType, aspectType); } public ResolvedMember getMatchingSyntheticMember(Member member) { return munger.getMatchingSyntheticMember(member, aspectType); } public int compareTo(Object other) { ConcreteTypeMunger o = (ConcreteTypeMunger) other; ResolvedType otherAspect = o.aspectType; if (aspectType.equals(otherAspect)) { return getSignature().getStart() < o.getSignature().getStart() ? -1 : +1; } else if (aspectType.isAssignableFrom(o.aspectType)) { return +1; } else if (o.aspectType.isAssignableFrom(aspectType)) { return -1; } else { return 0; } } public int fallbackCompareTo(Object other) { // ConcreteTypeMunger o = (ConcreteTypeMunger) other; return 0; } /** * returns true if the ITD target type used type variables, for example I. When they are specified like this, the ITDs * 'share' type variables with the generic type. Usually this method is called because we need to know whether to tailor the * munger for addition to a particular type. For example: * interface I {} * * aspect X implements I { * List I.foo { return null; } * } * In this case the munger matches X but it matches with the form * List foo() { return null; } * */ public boolean isTargetTypeParameterized() { if (munger == null) { return false; } return munger.sharesTypeVariablesWithGenericType(); } /** * For an ITD made on a generic type that shares type variables with that target type, this method will tailor the ITD for a * particular usage of the generic type - either in its raw or parameterized form. */ public abstract ConcreteTypeMunger parameterizedFor(ResolvedType targetType); public boolean isLateMunger() { if (munger == null) { return false; } return munger.isLateMunger(); } public abstract ConcreteTypeMunger parameterizeWith(Map parameterizationMap, World world); /** * Some type mungers are created purely to help with the implementation of shadow mungers. For example to support the cflow() * pointcut we create a new cflow field in the aspect, and that is added via a BcelCflowCounterFieldAdder. * * During compilation we need to compare sets of type mungers, and if some only come into existence after the 'shadowy' type * things have been processed, we need to ignore them during the comparison. * * Returning true from this method indicates the type munger exists to support 'shadowy' stuff - and so can be ignored in some * comparison. */ public boolean existsToSupportShadowMunging() { if (munger != null) { return munger.existsToSupportShadowMunging(); } return false; } public boolean shouldOverwrite() { return true; } }