/*******************************************************************************
 * Copyright (c) 2009 SpringSource and others.
 * 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:
 *     Andrew Eisenberg - initial API and implementation
 *******************************************************************************/

package org.eclipse.ajdt.internal.ui.refactoring;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.aspectj.asm.IProgramElement;
import org.aspectj.asm.IProgramElement.Kind;
import org.eclipse.ajdt.core.AspectJCore;
import org.eclipse.ajdt.core.codeconversion.AspectsConvertingParser;
import org.eclipse.ajdt.core.javaelements.AJCompilationUnit;
import org.eclipse.ajdt.core.javaelements.DeclareElement;
import org.eclipse.ajdt.core.javaelements.DeclareElementInfo;
import org.eclipse.ajdt.core.javaelements.IAspectJElement;
import org.eclipse.ajdt.core.javaelements.IntertypeElement;
import org.eclipse.ajdt.core.model.AJProjectModelFacade;
import org.eclipse.ajdt.core.model.AJProjectModelFactory;
import org.eclipse.ajdt.core.model.AJRelationshipManager;
import org.eclipse.ajdt.core.model.AJRelationshipType;
import org.eclipse.ajdt.ui.AspectJUIPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTRequestor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.manipulation.ImportReferencesCollector;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.NameLookup.Answer;
import org.eclipse.jface.text.Region;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.ChangeDescriptor;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.ltk.core.refactoring.resource.DeleteResourceChange;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;

/**
 * @author Andrew Eisenberg
 * @author Andy Clement
 */
public class PushInRefactoring extends Refactoring {

    public static final String ALL_ITDS = "all.itds";
    public static final String DELETE_EMPTY = "delete.empty";
    
    /**
     * Since each class is visited multiple times, and each visit may introduce
     * new imports, we must delay import rewriting
     * until each class has its ITDs already pushed in.
     *
     */
    private class PerUnitInformation {
        final Set<SimpleName> staticImports;
        final Set<SimpleName> typeImports;
        final Set<String> extraImports;
        final ICompilationUnit unit;
        
        // all declare parents (extends) to insert
        final Map<IType, Set<String>> declareParents;
        
        PerUnitInformation(ICompilationUnit unit) {
            staticImports = new HashSet<SimpleName>();
            typeImports = new HashSet<SimpleName>();
            extraImports = new HashSet<String>();
            this.unit = unit;
            declareParents = new HashMap<IType, Set<String>>();
        }
        
        // does not handle imports for declare parents
        void rewriteImports() throws CoreException {
            // first check to see if this unit has been deleted.
            Change change = allChanges.get(unit);
            if (! (change instanceof TextFileChange)) {
                return;
            }
            
            ImportRewrite rewrite = ImportRewrite.create(unit, true);
            for (Name name : typeImports) {
                ITypeBinding binding = name.resolveTypeBinding();
                if (binding != null) {
                    rewrite.addImport(binding);
                }
            }
            for (Name name : staticImports) {
            	 ITypeBinding binding = name.resolveTypeBinding();
            	 if (binding != null) {
            		 rewrite.addImport(name.resolveTypeBinding());
            	 }
            }

            for (String qualName : extraImports) {
                rewrite.addImport(qualName);
            }
            TextEdit importEdit = rewrite.rewriteImports(new NullProgressMonitor());
            
            TextFileChange textChange = (TextFileChange) change;
            textChange.getEdit().addChild(importEdit);
        }

        void computeImports(List<IMember> itds, ICompilationUnit ajUnit, IProgressMonitor monitor)
                throws JavaModelException {
            IJavaProject project = ajUnit.getJavaProject();
            ASTParser parser = ASTParser.newParser(AST.JLS8);
            parser.setProject(project);
            parser.setResolveBindings(true);
            parser.setSource(ajUnit);
            parser.setKind(ASTParser.K_COMPILATION_UNIT);
            CompilationUnit ajAST = (CompilationUnit) parser.createAST(monitor);

            for (IMember itd : itds) {
                ISourceRange range = itd.getSourceRange();
                ImportReferencesCollector.collect(ajAST, project, new Region(
                        range.getOffset(), range.getLength()),
                        typeImports, staticImports);
                if (itd instanceof DeclareElement) {
                    DeclareElement declare = (DeclareElement) itd;
                    // no types added for declare removers
                    if (!((DeclareElementInfo) declare.getElementInfo()).isAnnotationRemover()) {
                        String qualType = getQualifiedTypeForDeclareAnnotation(declare);
                        if (qualType != null && qualType.length() > 0) {
                            extraImports.add(qualType);
                        }
                        List<Type> types = getExtraImportsFromDeclareElement(declare, ajAST);
                        for (Type type : types) {
                            ImportReferencesCollector.collect(type, project, new Region(
                                    type.getStartPosition(), type.getLength()),
                                    typeImports, staticImports);
                        }
                    }
                }
            }
        }
        
        // This method finds the extra imports required by a declare element
        // (eg- used inside of a declare @annotation's annotation)
        // We take advantage of the format of the converted source from aspectj to java
        // the last fields of the last type when following a particular naming convention, 
        // are around to force import statements to exist.  We can read them and use them 
        // to seed the extra imports list
        private List<Type> getExtraImportsFromDeclareElement(DeclareElement itd,
                CompilationUnit ajAST) {
            int numTypes = ajAST.types().size();
            if (numTypes == 0) {
                return Collections.emptyList();
            }
            
            String details = null;
            AbstractTypeDeclaration lastType = (AbstractTypeDeclaration) ajAST.types().get(numTypes-1);
            @SuppressWarnings("unchecked")
            List<BodyDeclaration> bodyDecls = lastType.bodyDeclarations();
            List<Type> extraSimpleNames = new LinkedList<Type>();
            for (int i = bodyDecls.size()-1; i >= 0; i--) {
                BodyDeclaration decl = bodyDecls.get(i);
                if (decl.getNodeType() == ASTNode.FIELD_DECLARATION) {
                    FieldDeclaration fDecl = (FieldDeclaration) decl;
                    if (fDecl.fragments().size() == 1) {
                        VariableDeclarationFragment frag = (VariableDeclarationFragment) fDecl.fragments().get(0);
                        if (frag.getName().toString().startsWith(AspectsConvertingParser.ITD_INSERTED_IDENTIFIER)) {
                            if (details == null) {
                                IProgramElement ipe = getModel(itd).javaElementToProgramElement(itd);
                                details = ipe.getDetails();
                            }
                            Type type = fDecl.getType();
                            // only add if this type exists in the declare @annotation 
                            if (details.indexOf(type.toString()) != -1) {
                                 extraSimpleNames.add(type);
                            }
                            
                            continue;
                        }
                    }
                }
                // break on the first body declaration that does not conform
                break;
            }
            return extraSimpleNames;
        }

        public void addDeclarParents(IType type, List<String> parentTypes) {
            Set<String> set = declareParents.get(type);
            if (set == null) {
                set = new LinkedHashSet<String>();
                declareParents.put(type, set);
            }
            set.addAll(parentTypes);
            for (String parent : parentTypes) {
                String[] split = parent.split("<|>|,");
                for (String name : split) {
                    extraImports.add(name.trim());
                }
            }
        }
    }
    
    private boolean deleteEmpty = true;
    
    private Map<ICompilationUnit, Change> allChanges = null; 

    private List<IMember> itds = null;
    
    private Map<IProject, AJProjectModelFacade> allModels = new HashMap<IProject, AJProjectModelFacade>();
    private AJProjectModelFacade getModel(IJavaElement elt) {
        IProject project = elt.getJavaProject().getProject();
        AJProjectModelFacade model = allModels.get(project);
        if (model == null) {
            model = AJProjectModelFactory.getInstance().getModelForProject(project);
            allModels.put(project, model);
        }
        return model;
    }
    
    private Map<IJavaProject, NameLookup> allLookups = new HashMap<IJavaProject, NameLookup>();
    private NameLookup getLookup(IJavaElement elt) throws JavaModelException {
        IJavaProject javaProject = elt.getJavaProject();
        NameLookup nameLookup = allLookups.get(javaProject);
        if (nameLookup == null) {
            nameLookup = ((JavaProject) javaProject).newNameLookup(DefaultWorkingCopyOwner.PRIMARY);
            allLookups.put(javaProject, nameLookup);
        }
        return nameLookup;
    }
    

    @Override
	public RefactoringStatus checkFinalConditions(IProgressMonitor monitor)
            throws CoreException, OperationCanceledException {
        final RefactoringStatus status = new RefactoringStatus();
        try {
            monitor.beginTask("Checking final conditions...", 2);
            allChanges = new LinkedHashMap<ICompilationUnit, Change>();
            // map from AJCUs to contained ITDs that will be pushed in
            Map<ICompilationUnit, List<IMember>> unitToITDs = new HashMap<ICompilationUnit, List<IMember>>();
            Map<ICompilationUnit, PerUnitInformation> importsMap = new HashMap<ICompilationUnit, PerUnitInformation>();

            for (IMember itd : itds) {
                if (itd instanceof IAspectJElement && ((IAspectJElement) itd).getAJKind() == Kind.DECLARE_PARENTS) {
                    AJProjectModelFacade model = getModel(itd);
                    // rememebr the types pushed in and associate them with the target types
                    List<IJavaElement> elts = model.getRelationshipsForElement(itd, AJRelationshipManager.DECLARED_ON);
                    IProgramElement ipe = model.javaElementToProgramElement(itd);
                    List<String> parentTypes = ipe.getParentTypes();
                    for (IJavaElement elt : elts) {
                        if (elt.getElementType() == IJavaElement.TYPE) {
                            IType type = (IType) elt;
                            ICompilationUnit owningUnit = type.getCompilationUnit();
                            PerUnitInformation holder = importsMap.get(owningUnit);
                            if (holder == null) {
                                holder = new PerUnitInformation(owningUnit);
                                importsMap.put(owningUnit, holder);
                            }
                            holder.addDeclarParents(type, parentTypes);
                        }
                    }
                }
                
                // remember the ITDs per compilation unit so that we can remove them later
                ICompilationUnit unit = itd.getCompilationUnit();
                List<IMember> itdList = unitToITDs.get(unit);
                if (itdList == null) {
                    itdList = new LinkedList<IMember>();
                    unitToITDs.put(unit, itdList);
                }
                itdList.add(itd);
            }
            
            // now do the work ITDs and declare annotation
            for (Map.Entry<ICompilationUnit,List<IMember>> entry :  unitToITDs.entrySet()) {
                status.merge(checkFinalConditionsForITD(
                        entry.getKey(), entry.getValue(), importsMap,
                        monitor));
            }
            
            // now go through and create the import edits
            for (PerUnitInformation holder : importsMap.values()) {
                holder.rewriteImports();
            }
            
        } finally {
            allLookups.clear();
            allModels.clear();
            monitor.done();
        }
        return status;
    }

    /**
     * Checks the conditions for a single {@link AJCompilationUnit}
     * @param ajUnit the unit to check
     * @param itdsForUnit all itds in this unit
     * @param imports a map from target {@link ICompilationUnit} to imports that need to be added
     * initially empty, but populated in this method
     * @param monitor
     * @return
     * @throws JavaModelException
     */
    private RefactoringStatus checkFinalConditionsForITD(final ICompilationUnit ajUnit, 
            final List<IMember> itdsForUnit, 
            final Map<ICompilationUnit, PerUnitInformation> imports, 
            final IProgressMonitor monitor) throws JavaModelException {
        
        final RefactoringStatus status = new RefactoringStatus();
        
        // group all of the ITD targets by the ICompilationUnit that they are in
        final Map<ICompilationUnit, Set<IMember>> unitsToTypes = getUnitTypeMap(getTargets(itdsForUnit));
        
        // group all of the ICompilationUnits by project
        final Map<IJavaProject, Collection<ICompilationUnit>> projects= new HashMap<IJavaProject, Collection<ICompilationUnit>>();
        for (ICompilationUnit targetUnit : unitsToTypes.keySet()) {
            IJavaProject project= targetUnit.getJavaProject();
            if (project != null) {
                Collection<ICompilationUnit> collection = projects.get(project);
                if (collection == null) {
                    collection= new ArrayList<ICompilationUnit>();
                    projects.put(project, collection);
                }
                collection.add(targetUnit);
            }
        }
        
        // also add the ajunit to the collection of affected units
        Collection<ICompilationUnit> units;
        IJavaProject aspectProject = ajUnit.getJavaProject();
        if (projects.containsKey(aspectProject)) {
            units = projects.get(aspectProject);
        } else {
            units = new ArrayList<ICompilationUnit>();
            projects.put(aspectProject, units);
        }
        units.add(ajUnit);
        
        // this requestor performs the real work
        ASTRequestor requestors = new ASTRequestor() {
            @Override
			public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
                try {
                    
                    // compute the imports that this itd adds to this unit
                    PerUnitInformation holder;
                    if (imports.containsKey(source)) {
                        holder = imports.get(source);
                    } else {
                        holder = new PerUnitInformation(source);
                        imports.put(source, holder);
                    }
                    holder.computeImports(itdsForUnit, ajUnit, monitor);

                    for (Entry<IType, Set<String>> entry : holder.declareParents.entrySet()) {
                        rewriteDeclareParents(entry.getKey(), ast, entry.getValue(), source);
                    }
                    
                    // make the simplifying assumption that the CU that contains the
                    // ITD does not also contain a target type
                    // Bug 310020
                    if (isCUnitContainingITD(source, itdsForUnit.get(0))) {
                        // this is an AJCU.
                        rewriteAspectType(itdsForUnit, source, ast);
                    } else {
                        // this is a regular CU
                        
                        for (IMember itd : itdsForUnit) {
                            
                            // filter out the types not affected by itd 
                            Collection<IMember> members = new ArrayList<IMember>();
                            members.addAll(unitsToTypes.get(source));
                            AJProjectModelFacade model = getModel(itd);
                            List<IJavaElement> realTargets;
                            if (itd instanceof IAspectJElement && ((IAspectJElement) itd).getAJKind().isDeclareAnnotation()) {
                                realTargets = model
                                        .getRelationshipsForElement(
                                                itd,
                                                AJRelationshipManager.ANNOTATES);
                            } else {
                                // regular ITD or an ITIT
                                realTargets = model
                                        .getRelationshipsForElement(
                                                itd,
                                                AJRelationshipManager.DECLARED_ON);
                            }
                            for (Iterator<IMember> memberIter = members.iterator(); memberIter
                                    .hasNext();) {
                                IMember member = memberIter.next();
                                if (!realTargets.contains(member)) {
                                    memberIter.remove();
                                }
                            }

                            if (members.size() > 0) {
                                // if declare parents, store until later
                                if (itd instanceof IAspectJElement && 
                                        ((IAspectJElement) itd).getAJKind() == Kind.DECLARE_PARENTS) {
                                    // already taken care of
                                }
                                applyTargetTypeEdits(itd, source, members);
                            }
                        }  // for (Iterator itdIter = itdsForUnit.iterator(); itdIter.hasNext();) {
                    }
                } catch (JavaModelException e) {
                } catch (CoreException e) {
                }
            }
        };
        IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 1);
        try {
            try {
                final Set<IJavaProject> set= projects.keySet();
                subMonitor.beginTask("Compiling source...", set.size());
                for (IJavaProject project : projects.keySet()) {
                    ASTParser parser= ASTParser.newParser(AST.JLS8);
                    parser.setProject(project);
                    parser.setResolveBindings(true);
                    Collection<ICompilationUnit> collection= projects.get(project);
                    parser.createASTs(collection.toArray(
                            new ICompilationUnit[collection.size()]), new String[0], 
                            requestors, new SubProgressMonitor(subMonitor, 1));
                }

            } finally {
                subMonitor.done();
            }
            
        } finally {
            subMonitor.done();
        }
        return status;
    }


    /**
     * Removes all ITDs in the given compilation unit.
     * Will delete an aspect if it has no more members.
     * Will delete an {@link AJCompilationUnit} if all 
     * of its types are deleted.
     * @param itdsForUnit the ITDs for the given unit
     * @param source 
     * @param ast used to calculate imports
     * @throws JavaModelException
     * @throws CoreException
     */
    protected void rewriteAspectType(List<IMember> itdsForUnit,
            ICompilationUnit source, CompilationUnit ast) throws JavaModelException, CoreException {
            
        // used to keep track of aspect types that are deleted.
        Map<IType, Integer> removalStored = new HashMap<IType, Integer>();
        Map<IType, List<DeleteEdit>> typeDeletes = new HashMap<IType, List<DeleteEdit>>();
        
        // go through each ITD and create a delete edit for it
        for (IMember itd : itdsForUnit) {
            IType parentAspectType = (IType) itd.getParent();
            int numRemovals;
            if (removalStored.containsKey(parentAspectType)) {
                numRemovals = removalStored.get(parentAspectType).intValue();
                removalStored.put(parentAspectType, new Integer(++numRemovals));
            } else {
                removalStored.put(parentAspectType, new Integer(1));
            }
            List<DeleteEdit> deletes;
            if (typeDeletes.containsKey(parentAspectType)) {
                deletes = typeDeletes.get(parentAspectType);
            } else {
                deletes = new LinkedList<DeleteEdit>();
                typeDeletes.put(parentAspectType, deletes);
            }
            
            DeleteEdit edit = new DeleteEdit(itd.getSourceRange().getOffset(), itd.getSourceRange().getLength()+1);
            deletes.add(edit);
        }
        
        if (deleteTypes(ast, typeDeletes, removalStored)) {
            allChanges.put(source, new DeleteResourceChange(source.getResource().getFullPath(), false));
        } else {
            applyAspectEdits(source, typeDeletes);
        }
    }

    /**
     * Adds the specified new parents to the type.
     * Need to determine if the new paretns are extends or implements
     * 
     * FIXADE will not handle generic types
     * @param targetType
     * @param astUnit
     * @param newParents
     * @param holder
     * @throws JavaModelException 
     */
    @SuppressWarnings("unchecked")
    private void rewriteDeclareParents(IType targetType, CompilationUnit astUnit, Set<String> newParents,
            ICompilationUnit unit) throws JavaModelException {
        
        // find the Type declaration in the ast
        TypeDeclaration typeDecl = findType(astUnit, targetType.getElementName());
        if (typeDecl == null) {
            createJavaModelException("Couldn't find type " + targetType.getElementName() + " in " +
            unit.getElementName());
        }
        
        // convert all parents to simple names
        List<String> simpleParents = new ArrayList<String>(newParents.size());
        for (String qual : newParents) {
            simpleParents.add(convertToSimple(qual));
        }
        
        // now remove any possible duplicates
        Type superclassType = typeDecl.getSuperclassType();
        Type supr = superclassType;
        if (supr != null && supr.isSimpleType()) {
            simpleParents.remove(((SimpleType) supr).getName().getFullyQualifiedName());
        }
        for (Type iface : (Iterable<Type>) typeDecl.superInterfaceTypes()) {
            if (iface.isSimpleType()) {
                simpleParents.remove(((SimpleType) iface).getName().getFullyQualifiedName());
            }
        }

        // Find the super class if exists
        // make assumption that there is at most one super class defined.
        // if this weren't the case, then there would be a compile error
        // and it would not be possible to invoke refactoring
        String newSuper = null;
        for (String parent : newParents) {
            if (isClass(parent, targetType)) {
            	newSuper = convertToSimple(parent);
                simpleParents.remove(newSuper);
            }
        }
        
        // do the rewrite.  Only need to add simple names since imports are already taken care of
        // in the holder
        ASTRewrite rewriter = ASTRewrite.create(astUnit.getAST());
        AST ast = typeDecl.getAST();
        if (newSuper != null) {
            Type newSuperType = createTypeAST(newSuper, ast);
            if (superclassType == null) {
                rewriter.set(typeDecl, TypeDeclaration.SUPERCLASS_TYPE_PROPERTY, newSuperType, null);
            } else {
                rewriter.replace(superclassType, newSuperType, null);
            }
        }
        if (simpleParents.size() > 0) {
            ListRewrite listRewrite = rewriter.getListRewrite(typeDecl, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY);
            for (String simpleParent : simpleParents) {
                listRewrite.insertLast(createTypeAST(simpleParent, ast), null);
            }
        }        
        // finally, add the new change
        TextEdit edit = rewriter.rewriteAST();
        if (!isEmptyEdit(edit)) {
            TextFileChange change= (TextFileChange) allChanges.get(unit);
            if (change == null) {
                change= new TextFileChange(unit.getElementName(), (IFile) unit.getResource());
                change.setTextType("java");
                change.setEdit(new MultiTextEdit());
                allChanges.put(unit, change);
            }
            change.getEdit().addChild(edit);
        }
    }


    private Type createTypeAST(String newSuper, AST ast) {
        String toParse = newSuper + " t;";
        ASTParser parser = ASTParser.newParser(AST.JLS8);
        parser.setSource((toParse).toCharArray());
        parser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
        ASTNode astNode = parser.createAST(null);
        Type t = null;
        if (astNode instanceof TypeDeclaration) {
            Object object = ((TypeDeclaration) astNode).bodyDeclarations().get(0);
            if (object instanceof FieldDeclaration) {
                t = ((FieldDeclaration) object).getType();
                t = (Type) ASTNode.copySubtree(ast, t);
            }
        }
        if (t == null) {
            t = ast.newSimpleType(ast.newSimpleName("MISSING"));
        }
        return t;
    }

    /**
     * Converts from a possibly generic fully qualified type name to a simple fully
     * qualified type name
     * @param qualName
     * @return
     */
    String convertToSimple(String qualName) {
        char[] charArray = qualName.toCharArray();
        StringBuilder candidate = new StringBuilder(charArray.length);
        StringBuilder complete = new StringBuilder(charArray.length);
        for (char c : charArray) {
            switch (c) {
                case '.':
                    candidate.delete(0, candidate.length());
                    break;
                case '<':
                case ',':
                case '>':
                    complete.append(candidate).append(c);
                    candidate.delete(0, candidate.length());
                    break;
                default:
                    candidate.append(c);
            }
        }
        complete.append(candidate);
        return complete.toString();
    }


    /**
     * @return true iff name is the fully qualified name of a class, false if an interface, enum, etc 
     * @throws JavaModelException 
     */
    private boolean isClass(String name, IType type) throws JavaModelException {
        String erasedName = name;
        int genericsIndex = name.indexOf('<');
        if (genericsIndex > 0) {
            erasedName = name.substring(0, genericsIndex);
        }
        
        int dotIndex = erasedName.lastIndexOf('.');
        String packageName;
        String simpleName;
        if (dotIndex > 0) {
            packageName = erasedName.substring(0, dotIndex);
            simpleName = erasedName.substring(dotIndex +1);
        } else {
            packageName = "";
            simpleName = erasedName;
        }
        IType found = findType(packageName, simpleName, type);
        return found != null && found.isClass();
    } 
    private IType findType(String packageName, String simpleName, IType type) throws JavaModelException {
        NameLookup lookup = getLookup(type);
        Answer answer = lookup.findType(simpleName, packageName, false, NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES, true, false, false, null);
        if (answer != null) {
            return answer.type;
        }
        // might be an inner type
        int dotIndex = packageName.lastIndexOf('.');
        if (dotIndex > 0) {
            IType foundType = findType(packageName.substring(0, dotIndex), packageName.substring(dotIndex+1), type);
            if (foundType != null && foundType.getType(simpleName).exists()) {
                return foundType.getType(simpleName);
            }
        }
        return null;
    }


    private void createJavaModelException(String message)
            throws JavaModelException {
        throw new JavaModelException(new CoreException(new Status(IStatus.INFO, AspectJUIPlugin.PLUGIN_ID,
        		message)));
    }

    @SuppressWarnings("unchecked")
    private TypeDeclaration findType(CompilationUnit ast, String name) {
        for (TypeDeclaration type : (Iterable<TypeDeclaration>) ast.types()) {
            if (type.getName().getIdentifier().equals(name)) {
                return type;
            }
        }
        return null;
    }
    
    /**
     * Deletes all aspect types that have no more children
     * returns true if the compilation unit should be deleted
     * @param ast
     * @param typeDeletes
     * @param removalStored
     * @return
     * @throws JavaModelException
     */
    private boolean deleteTypes(CompilationUnit ast, Map<IType, List<DeleteEdit>> typeDeletes,
            Map<IType, Integer> removalStored) throws JavaModelException {
        if (!deleteEmpty) {
            return false;
        }
        int typesDeleted = 0;
        for (Map.Entry<IType, Integer> entry : removalStored.entrySet()) {
            IType type = entry.getKey();
            int removals = entry.getValue();
            
            // check to see if all of the type's children 
            // have been removed.  If so, delete the type 
            if (type.getChildren().length == removals) {
                @SuppressWarnings("unchecked")
                List<AbstractTypeDeclaration> typeNodes = ast.types();
                for (AbstractTypeDeclaration typeNode : typeNodes) {
                    if (typeNode.getName().toString().equals(type.getElementName())) {
                        List<DeleteEdit> deletes = typeDeletes.get(type);
                        deletes.clear();
                        deletes.add(new DeleteEdit(type.getSourceRange().getOffset(), type.getSourceRange().getLength()));
                        typesDeleted++;
                    }
                }
            }
        }
        
        // check to see if all types have been deleted.
        return (ast.types().size() == typesDeleted);
    }



    private void applyTargetTypeEdits(IMember itd,
            ICompilationUnit source, Collection<IMember> targets) throws CoreException, JavaModelException {
        MultiTextEdit multiEdit = new MultiTextEdit();
        for (IMember target : targets) {
            TextEdit edit = null;
            if (itd instanceof IAspectJElement) {
                IAspectJElement ajElement = (IAspectJElement) itd;
                if (itd instanceof IntertypeElement) {
                    if (target instanceof IType) {
                        IType type = (IType) target;
                        // ignore ITD fields and constructors on interfaces
                        if (type.isInterface() && ajElement.getAJKind() != Kind.INTER_TYPE_METHOD) {
                            edit = null;
                        } else {
                            edit = createEditForITDTarget((IntertypeElement) itd, type);
                        }
                    }
                } else if (ajElement.getAJKind().isDeclareAnnotation()) {
                    edit = createEditForDeclareTarget((DeclareElement) itd, target);
                }
            } else if (itd instanceof IType) {
                // an ITIT
                edit = createEditForIntertypeInnerType((IType) itd, (IType) target);
            }
            if (edit != null) {
                multiEdit.addChild(edit);
            }
        }
        
        if (!isEmptyEdit(multiEdit)) {
            TextFileChange change= (TextFileChange) allChanges.get(source);
            if (change == null) {
                change= new TextFileChange(source.getElementName(), (IFile) source.getResource());
                change.setTextType("java");
                change.setEdit(new MultiTextEdit());
                allChanges.put(source, change);
            }
            change.getEdit().addChild(multiEdit);
        }
    }


    private String getQualifiedTypeForDeclareAnnotation(DeclareElement itd) {
        IProgramElement ipe = getModel(itd).javaElementToProgramElement(itd);
        if (ipe != null) {
            return ipe.getAnnotationType();
        }
        return null;
    }

    /**
     * Creates the text edit for pushing in an intertype inner type
     * @param itit the intertype inner type to push in 
     * @param target the target to push the itit into.
     * @return
     */
    private TextEdit createEditForIntertypeInnerType(IType itit, IType target) throws JavaModelException {
        String source = itit.getSource();
        // now, we must replace the '.' and the preceding identifier in the type name
        int nameOffset = itit.getNameRange().getOffset() - itit.getSourceRange().getOffset();
        int dotOffset = source.lastIndexOf('$', nameOffset);
        int classIndex = source.lastIndexOf("class ", dotOffset);
        source = "\n\t" + source.substring(0, classIndex + "class ".length()) + source.substring(dotOffset + 1, source.length()) + "\n";
        return new InsertEdit(getITDInsertLocation(target), source);
    }

    private TextEdit createEditForDeclareTarget(DeclareElement itd,
            IMember target) throws JavaModelException {
        DeclareElementInfo declareElementInfo = (DeclareElementInfo) itd.getElementInfo();
        if (declareElementInfo.isAnnotationRemover()) {
            // must use the model to access removals
            AJProjectModelFacade model = getModel(itd);
            IProgramElement ipe = model.javaElementToProgramElement(itd);
            return getAnnotationRemovalEdit(target, ipe.getRemovedAnnotationTypes());
        } else {
            return new InsertEdit(getDeclareInsertLocation(target), getTextForDeclare(itd));
        }
    }

    /**
     * Delete the specified annotations on the target
     * @param target target element to have annotations to delete
     * @param removedAnnotationTypes annotations to delete
     * @return the delete edit.  May be a MultiText edit
     * if multiple annotations are removed
     * @throws JavaModelException 
     */
    private TextEdit getAnnotationRemovalEdit(IMember target,
            String[] removedAnnotationTypes) throws JavaModelException {
        if (target instanceof IAnnotatable) {
            IAnnotatable annotatable = (IAnnotatable) target;
            IAnnotation[] anns = annotatable.getAnnotations();
            List<DeleteEdit> deletes = new ArrayList<DeleteEdit>(removedAnnotationTypes.length);
            for (String removedType : removedAnnotationTypes) {
                // there can be only one match per removed type
                // however, there can be two annotations with the
                // same simple name on the member, but at least one has
                // a matching qual name.
                // So, if there is a simple name match, keep on looking, 
                // but a qual name match, end it.
                DeleteEdit edit = null; 
                for (IAnnotation ann : anns) {
                    // don't know if ann is a simple or a qualified name, 
                    // so check both.
                    String annName = ann.getElementName();
                    boolean qualMatch = removedType.equals(annName);
                    boolean simpleMatch = removedType.endsWith("." + annName);
                    if (simpleMatch || qualMatch) {
                        // match!
                        ISourceRange range = ann.getSourceRange();
                        edit = new DeleteEdit(range.getOffset(), range.getLength());
                        if (qualMatch) {
                            // can only be one qualified match
                            break;
                        }
                    }
                }
                if (edit != null) {
                    deletes.add(edit);
                }
            }
            if (deletes.size() == 0) {
                return null;
            } else if (deletes.size() == 1) {
                return deletes.get(0);
            } else {
                MultiTextEdit multi = new MultiTextEdit();
                for (DeleteEdit delete : deletes) {
                    multi.addChild(delete);
                }
                return multi;
            }
        } else {
            // nothing found
            return null;
        }
    }

    private String getTextForDeclare(DeclareElement itd) throws JavaModelException {
        IProgramElement ipe = getModel(itd).javaElementToProgramElement(itd);
        if (ipe != null) {
            String details = ipe.getDetails();
            int colonIndex = details.indexOf(':');
            String text = details.substring(colonIndex+1).trim();
            if (itd.getAJKind() == Kind.DECLARE_ANNOTATION_AT_TYPE) {
                // assume top level type
                return text + "\n";
            } else {
                return text + "\n\t";
            }
        } else {
            throw new RuntimeException("Could not find program element in AspectJ model for " + itd.getHandleIdentifier());
        }
    }   

    private int getDeclareInsertLocation(IMember target) throws JavaModelException {
        return target.getSourceRange().getOffset();
    }

    private TextEdit createEditForITDTarget(IntertypeElement itd, IType target) 
            throws JavaModelException {
        // don't add fields or constructors to interfaces
        TextEdit edit;
        if (target.isInterface()) {
            edit = new InsertEdit(getITDInsertLocation(target), getTargetTextForInterface(itd));
        } else {
            edit = new InsertEdit(getITDInsertLocation(target), getTargetTextForClass(itd));
        }
        return edit;
    }

    private String getTargetTextForClass(IntertypeElement itd) throws JavaModelException {
        String itdName = itd.getElementName();
        String[] splits = itdName.split("\\.");
        String newName = splits[splits.length-1];
        itdName = itdName.replaceAll("\\.", "\\\\\\$");
        
        // check for constructor
        if (itdName.endsWith("_new")) {
            // check to see if constructor
            String maybeConstructor = itdName.substring(0, itdName.length()-"_new".length());
            String[] maybeConstructorArr = maybeConstructor.split("\\\\\\$");
            if (maybeConstructorArr.length == 2 && maybeConstructorArr[0].equals(maybeConstructorArr[1])) {
                itdName = maybeConstructorArr[0] +"\\$new";
                newName = maybeConstructorArr[0];
            }
        }

        String targetSource = getTargetSource(newName, itd);
        targetSource = "\n\t" + targetSource + "\n";
        // also replace other pplaces where the itdName may exist
        targetSource = targetSource.replaceAll(itdName, newName);
        
        return targetSource;
    }

    private String getTargetTextForInterface(IntertypeElement itd) throws JavaModelException {
        String itdName = itd.getElementName();
        String[] splits = itdName.split("\\.");
        String newName = splits[splits.length-1];
        itdName = itdName.replaceAll("\\.", "\\\\\\$");
        String targetSource = getTargetSource(newName, itd);
        int closeParen = targetSource.indexOf(")");  // assumption here...closing paren doesn't exist in comments
        if (closeParen >= 0) {
            targetSource = targetSource.substring(0, closeParen+1) + ';';
        }
        targetSource = "\n\t" + targetSource + "\n\n";
        // also replace any other occurrences of the itdName
        targetSource = targetSource.replaceAll(itdName, newName);
        return targetSource;
    }

    /**
     * get the target source and replace the ITD name with the new name
     * @param newName
     * @param itd
     * @return
     * @throws JavaModelException 
     */
    private String getTargetSource(String newName, IntertypeElement itd) throws JavaModelException {
        int itdStart = itd.getSourceRange().getOffset();
        int itdNameStart = itd.getTargetTypeSourceRange().getOffset() - itdStart;
        int itdNameEnd = itd.getNameRange().getOffset() + itd.getNameRange().getLength() - itdStart;
        String targetSource = itd.getSource();
        targetSource = targetSource.substring(0, itdNameStart) + newName + targetSource.substring(itdNameEnd);
        return targetSource;
    }

    private int getITDInsertLocation(IType type) throws JavaModelException {
        return type.getSourceRange().getOffset()+type.getSourceRange().getLength()-1;
    }


    private void applyAspectEdits(ICompilationUnit source, Map<IType, List<DeleteEdit>> typeDeletes) throws JavaModelException,
            CoreException {
        MultiTextEdit edit = new MultiTextEdit();
        for (List<DeleteEdit> deletesForOneType : typeDeletes.values()) {
            for (DeleteEdit delete : deletesForOneType) {
                edit.addChild(delete);
            }
        }
        
        if (!isEmptyEdit(edit)) {
            TextFileChange change= (TextFileChange) allChanges.get(source);
            if (change == null) {
                change= new TextFileChange(source.getElementName(), (IFile) source.getResource());
                change.setTextType("java");
                change.setEdit(edit);
                allChanges.put(source, change);
            } else {
                change.getEdit().addChild(edit);
            }
        }
    }
    



    /**
     * Finds all of the compilation units for the given array of target elements
     * @param targets an array of target elements that are the target of ITDs in a single Aspect
     * @return all of the targets grouped by their {@link ICompilationUnit} 
     */
    private Map<ICompilationUnit, Set<IMember>> getUnitTypeMap(IMember[] targets) {
        Map<ICompilationUnit, Set<IMember>> unitToTypes = new HashMap<ICompilationUnit, Set<IMember>>();
        for (int i = 0; i < targets.length; i++) {
            IMember target = targets[i];
            ICompilationUnit unit = target.getCompilationUnit();
            Set<IMember> currTypes;
            if (unitToTypes.containsKey(unit)) {
                currTypes = unitToTypes.get(unit);
            } else {
                currTypes = new HashSet<IMember>();
                unitToTypes.put(unit, currTypes);
            }
            currTypes.add(target);
        }
        return unitToTypes;
    }

    @Override
	public RefactoringStatus checkInitialConditions(IProgressMonitor monitor)
            throws CoreException, OperationCanceledException {
        if (monitor == null) {
            monitor = new NullProgressMonitor();
        }
        RefactoringStatus status= new RefactoringStatus();
        
        monitor.beginTask("Checking preconditions...", 1);

        if (itds.isEmpty()) {
            return RefactoringStatus.createWarningStatus("No Intertype declarations selected.  Nothing to do.");
        }
        
        try {
            for (IMember itd : itds) {
                status.merge(initialITDCheck(itd));
            }
        } finally {
            monitor.done();
        }
        return status;
    }
    
    
    private RefactoringStatus initialITDCheck(IMember itd) {
        RefactoringStatus status= new RefactoringStatus();
        
        if (itd == null) {
            status.merge(RefactoringStatus.createFatalErrorStatus("Intertype declaration has not been specified"));
            return status;
        }
        if (! (itd instanceof IAspectJElement)) {
            return status;
        }
        try {
            AJProjectModelFacade model = getModel(itd);
            if (!model.hasModel()) {
                status.merge(RefactoringStatus.createFatalErrorStatus("No crosscutting model available.  Rebuild project."));
            }
            ICompilationUnit unit = itd.getCompilationUnit();
            Object[] itdName = new Object[] { unit.getElementName()};
            if (!itd.exists()) {
                status.merge(RefactoringStatus.createFatalErrorStatus(MessageFormat.format("ITD ''{0}'' does not exist.", new Object[] { itd.getElementName()})));
            } else if (!unit.isStructureKnown()) {
                status.merge(RefactoringStatus.createFatalErrorStatus(MessageFormat.format("Compilation unit ''{0}'' contains compile errors.", itdName)));
            } else
                try {
                    if (unit.getResource().findMaxProblemSeverity(IMarker.MARKER, true, IResource.DEPTH_ZERO) >= IMarker.SEVERITY_ERROR) {
                        status.merge(RefactoringStatus.createFatalErrorStatus(MessageFormat.format("Compilation unit ''{0}'' contains compile errors.", itdName)));
                    }
                } catch (CoreException e) {
                    status.merge(RefactoringStatus.create(e.getStatus()));
                }
            // now check target types
            IMember[] targets = getTargets(Collections.singletonList(itd));
            if (targets.length > 0) {
                for (int i = 0; i < targets.length; i++) {
                    IMember target = targets[i];
                    if (!target.exists()) {
                        status.merge(RefactoringStatus.createFatalErrorStatus(
                                MessageFormat.format("Target type ''{0}'' does not exist.", new Object[] { target.getElementName()})));
                    } else if (target.isBinary()) {
                        status.merge(RefactoringStatus.createFatalErrorStatus(
                                MessageFormat.format("Target type ''{0}'' is binary.", new Object[] { target.getElementName()})));
                    } else if (!unit.isStructureKnown()) {
                        status.merge(RefactoringStatus.createFatalErrorStatus(
                                MessageFormat.format("Compilation unit ''{0}'' contains compile errors.", 
                                        new Object[] { target.getCompilationUnit().getElementName()})));
                    }
                }
            } else {
                status.merge(RefactoringStatus.createWarningStatus(MessageFormat.format("ITD ''{0}'' has no target.  This refactoring will delete the declaration.  " +
                		"Perhaps there is an unresolved compilation error?", itd.getElementName())));
            }
        } catch (JavaModelException e) {
            status.addFatalError("JavaModelException:\n\t" + e.getMessage() + "\n\t" + e.getJavaModelStatus().getMessage());
        }
        return status;
    }


    @Override
	public Change createChange(IProgressMonitor monitor) throws CoreException,
            OperationCanceledException {
        monitor.beginTask("Creating change...", 1);
        try {
            final Collection<Change> changes= allChanges.values();
            CompositeChange change= new CompositeChange(getName(), changes.toArray(new Change[changes.size()])) {
    
                @Override
				public ChangeDescriptor getDescriptor() {
                    return new RefactoringChangeDescriptor(createDescriptor());
                }

            };
            return change;
        } finally {
            monitor.done();
        }
    }
    
    public PushInRefactoringDescriptor createDescriptor() {
        StringBuffer projectsb = new StringBuffer();
        StringBuffer descriptionsb = new StringBuffer();
        StringBuffer commentsb = new StringBuffer();
        StringBuffer argssb = new StringBuffer();
        for (IMember itd : itds) {
            projectsb.append(itd.getJavaProject().getElementName() + "\n");
            descriptionsb.append(MessageFormat.format("Push In intertype declaration for ''{0}''\n", new Object[] { itd.getElementName()}));
            String itdLabel = getModel(itd).getJavaElementLinkName(itd);
            commentsb.append(MessageFormat.format("Push In intertype declaration for ''{0}''\n", new Object[] { itdLabel }));
            argssb.append(itd.getHandleIdentifier() + "\n");
        }
        Map<String, String> arguments = new HashMap<String, String>();
        arguments.put(ALL_ITDS, argssb.toString());
        return new PushInRefactoringDescriptor(
                projectsb.toString(), 
                descriptionsb.toString(), 
                commentsb.toString(), 
                arguments);
    }

    
    @Override
	public String getName() {
        return "Push-In";
    }


    public RefactoringStatus initialize(Map<String, String> arguments) {
        String value= arguments.get(ALL_ITDS);
        if (value != null) {
            String[] values = value.split("\\n");
            List<IMember> newitds = new ArrayList<IMember>(values.length);
            for (int i = 0; i < values.length; i++) {
                newitds.add((IMember) AspectJCore.create(value));
            }
            setITDs(newitds);
            return new RefactoringStatus();
        } else {
            return RefactoringStatus.createErrorStatus("No ITD specified.");
        }
    }
    
    public void setITDs(List<IMember> itds) {
        this.itds = itds;
    }
    
    public List<IMember> getITDs() {
        return itds;
    }


    /**
     * This method determines all of the targets of the set of ITDs passed in.
     * it does not distinguish between which type is affected by which ITD
     * later, we need to do that filtering
     * @param itds set of ITDs to putsh in from a single compilation unit
     * @return array of target elements for these ITDs.
     * @throws JavaModelException
     */
    private IMember[] getTargets(List<IMember> itds) throws JavaModelException {
        AJProjectModelFacade model = getModel(itds.get(0));
        List<IMember> targets = new ArrayList<IMember>();
        
        for (IMember itd : itds) {
            List<IJavaElement> elts;
            AJRelationshipType relationship = itd instanceof IAspectJElement && ((IAspectJElement) itd).getAJKind().isDeclareAnnotation() ?
                    AJRelationshipManager.ANNOTATES :
                        // either an ITD or an ITIT (IType)
                        AJRelationshipManager.DECLARED_ON;
            elts = model.getRelationshipsForElement(itd, relationship);

            for (IJavaElement elt : elts) {
                targets.add((IMember) elt);
            }
        }
        return targets.toArray(new IMember[targets.size()]);
    }

    private boolean isEmptyEdit(TextEdit edit) {
        return edit.getClass() == MultiTextEdit.class && !edit.hasChildren();
    }
    
    private boolean isCUnitContainingITD(ICompilationUnit unit, IMember itd) {
        return itd != null && itd.getCompilationUnit().equals(unit);
    }
}
