alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.modules.refactoring.api;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.*;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.jmi.javamodel.*;
import org.netbeans.jmi.javamodel.Import;
import org.netbeans.jmi.javamodel.NamedElement;
import org.netbeans.modules.java.JavaDataObject;
import org.netbeans.modules.javacore.ClassIndex;
import org.netbeans.modules.javacore.JMManager;
import org.netbeans.modules.javacore.internalapi.ExternalChange;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.modules.javacore.jmiimpl.javamodel.TypeClassImpl;
import org.netbeans.modules.refactoring.CheckUtils;
import org.netbeans.modules.refactoring.NbAbstractRefactoring;
import org.netbeans.modules.refactoring.RenameFullNameElement;
import org.netbeans.modules.refactoring.api.Problem;
import org.netbeans.modules.refactoring.classpath.RefactoringClassPathImplementation;
import org.netbeans.modules.refactoring.ui.RefactoringOperationListener;
import org.netbeans.spi.java.classpath.ClassPathFactory;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.text.PositionBounds;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;

public class MoveClassRefactoring extends NbAbstractRefactoring {
    
    private Map/**/   targetFileMap;
    private Map/**/   sourceObjectsMap;
    private Collection/**/        resources;
    private Collection                      otherDataObjects = Collections.EMPTY_LIST;
    private Map /**/sourceClassesMap;
    private Collection /**/      allClasses          = new ArrayList(10);
    private Map /**/ sourcePackages;
    private boolean                         particularClassSelected;
    private Map /**/     accessesOriginalPackageMap;
    private Map /**/     accessedByOriginalPackageMap;
    private Map /**/     movingToDefaultPackageMap;
    private Map /**/     movingFromDefaultPackageMap;
    private FileObject                      folder = null;
    private boolean                         invokedAfterDOMove;

    //private String targetPrefix = ""; //NOI18N
    //private DataObject movedSource;
    
    private boolean donePreCheck = false;

    private Map checkedSourcesMap;
    
    private int size;
    
    public MoveClassRefactoring(Collection resources, Collection otherDataObjects, FileObject folder) {
        this(resources);
        this.otherDataObjects = otherDataObjects;
        this.folder = folder;
    }
    
    public MoveClassRefactoring(Collection resources) {
        this(resources, false, false);
    }
    
    public MoveClassRefactoring(Collection resources, boolean particularClassSelected, boolean invokedAfterDOMove) {
        size = resources.size();
        this.sourceObjectsMap = new HashMap(size);
        this.targetFileMap = new HashMap(size);
        this.sourceClassesMap = new HashMap(size*2);
        this.accessesOriginalPackageMap = new HashMap(size);
        this.accessedByOriginalPackageMap = new HashMap(size);
        this.movingToDefaultPackageMap = new HashMap(size);
        this.movingFromDefaultPackageMap = new HashMap(size);
        this.checkedSourcesMap = new HashMap(size);
        this.invokedAfterDOMove = invokedAfterDOMove;
                
        for (Iterator i = resources.iterator(); i.hasNext();) {
            Resource r = (Resource) i.next();
            sourceObjectsMap.put(r, JavaMetamodel.getManager().getDataObject(r));
        }

        this.resources = resources;
        this.particularClassSelected = particularClassSelected;
        
        for (Iterator i = resources.iterator(); i.hasNext();) {
            Resource r = (Resource) i.next();
            List list = new LinkedList();
            list.addAll(r.getClassifiers());
            sourceClassesMap.put(r, (JavaClass []) list.toArray(new JavaClass[list.size()]));
            checkedSourcesMap.put(r, new HashSet());
        }
        
    }
    
    public void setClassPath() {
        setClassPath(resources);
    }
    
    public Problem preCheck() {
        for (Iterator i = resources.iterator(); i.hasNext(); ) {
            JavaClass[] sourceClasses = (JavaClass[]) sourceClassesMap.get(i.next());
            for (int x = 0; x < sourceClasses.length; x++)
                collectAllClasses(allClasses, sourceClasses [x]);
            
        }
        fireProgressListenerStart(PRE_CHECK, 7*size);
        
        for (Iterator i = resources.iterator(); i.hasNext();) {
            Resource r = (Resource) i.next();
            accessedByOriginalPackageMap.put(r, Boolean.valueOf(isAccessedByOriginalPackage(r)));
            JavaPackage sourcePackage = (JavaPackage) r.refImmediateComposite();
            movingFromDefaultPackageMap.put(r, Boolean.valueOf(sourcePackage == null));
            accessesOriginalPackageMap.put(r, Boolean.FALSE);
        }
        
        try {
            for (Iterator i = resources.iterator(); i.hasNext();) {
                Resource r = (Resource) i.next();
                JavaClass[] sourceClasses = (JavaClass[]) sourceClassesMap.get(r);
                
                if (sourceClasses.length == 0) {
                    return new Problem(true, getString("ERR_SourceWithoutClass")); // NOI18N
                }
                fireProgressListenerStep();
                if ((sourceClasses.length > 1) && particularClassSelected) {
                    return new Problem(true, getString("ERR_SourceWithMoreClasses")); // NOI18N
                }
                fireProgressListenerStep();
            }
            
            Problem problem = checkUsedElements(null);
            
            for (Iterator i = resources.iterator(); i.hasNext();) {
                Resource r = (Resource) i.next();
                fireProgressListenerStep();
                fireProgressListenerStep();
                Boolean boolVal = (Boolean) accessesOriginalPackageMap.get(r);
                boolean accessesOriginalPackage = boolVal != null ? boolVal.booleanValue() : false;
                boolean movingFromDefaultPackage = ((Boolean) movingFromDefaultPackageMap.get(r)).booleanValue();
                if (accessesOriginalPackage && movingFromDefaultPackage) {
                    Problem p = new Problem(false, getString("ERR_ClassToMoveInDefaultPackage")); // NOI18N
                    p.setNext(problem);
                    problem = p;
                }
            }
            
            fireProgressListenerStep();
            fireProgressListenerStep();
            problem = checkAccessesMyFeature(problem);
            
            fireProgressListenerStep();
            donePreCheck = true;
            return problem;
        } finally {
            fireProgressListenerStop();
        }
    }        
    
    public Problem prepare(Collection elements) {
        Problem problem = null;
        Problem p;
        if (!donePreCheck) {
            problem = preCheck();
            p = problem;
            while (p != null) {
                if (p.isFatal())
                    return problem;
                p = p.getNext();
            }
        }
                
        fireProgressListenerStart(PREPARE, 4);
        
        try {
//            if (targetFile == null) {
//                p = new Problem(true, getString("ERR_TargetFolderNotSet")); // NOI18N
//                p.setNext(problem);
//                return p;
//            }        
            fireProgressListenerStep();

            ClassPath thisCP = null;
            FileObject targetRoot = null;

            if (isPackageRename) {
                thisCP = ClassPath.getClassPath(folder, ClassPath.SOURCE);
                targetRoot = thisCP.findOwnerRoot(folder);
            }
            checkWhereUsed(elements);                        
            fireProgressListenerStep();
            
            for (Iterator i = resources.iterator(); i.hasNext();) {
                if (cancelRequest) {
                    return null;
                }
                Resource resource = (Resource) i.next();
                JavaPackage sourcePackage = (JavaPackage) resource.refImmediateComposite();
                Boolean boolVal = (Boolean) accessesOriginalPackageMap.get(resource);
                boolean accessesOriginalPackage = boolVal != null ? boolVal.booleanValue() : false;
                boolean movingFromDefaultPackage = ((Boolean) movingFromDefaultPackageMap.get(resource)).booleanValue();
                if (accessesOriginalPackage && !movingFromDefaultPackage && !containsImport(resource, sourcePackage.getName())) {
                    elements.add(new InsertImport(resource, sourcePackage.getName(), false));
                }
                fireProgressListenerStep();
                
                DataObject sourceObject = (DataObject) sourceObjectsMap.get(resource);
                if (isPackageRename) {
                    elements.add(new MoveClass(sourceObject, targetRoot, newPackageName, (JavaClass[]) sourceClassesMap.get(resource)));
                } else {
                    elements.add(new MoveClass(sourceObject, (FileObject) targetFileMap.get(resource), (JavaClass[]) sourceClassesMap.get(resource)));
                }
                fireProgressListenerStep();
            }
            
            removeUnusedImports(elements);
            
            for (Iterator i = otherDataObjects.iterator(); i.hasNext();) {
                elements.add(new MoveClass((DataObject) i.next(),targetRoot, newPackageName, null));
            }
            
            return problem;
        } finally {
            referencesIterator = null;
            fireProgressListenerStop();
        }
    }
    
    private Collection getOldPackages() {
        Collection set = new HashSet(3);
        for (Iterator i = resources.iterator(); i.hasNext();) {
            Resource r = (Resource) i.next();
            set.add(r.refImmediateComposite());
        }
        return set;
    }
    
    private Collection getEmptyPackages() {
        Collection packages = new HashSet(3);
        for (Iterator i = getOldPackages().iterator(); i.hasNext();) {
            JavaPackage pack = (JavaPackage) i.next();
            Collection packResources = new HashSet(pack.getResources());
            packResources.removeAll(resources);
            packResources.remove(null);
            if (packResources.isEmpty()) {
                packages.add(pack);
            }
        }
        return packages;
    }
    private void removeUnusedImports(Collection elements) {
        for (Iterator iter = getEmptyPackages().iterator(); iter.hasNext();) {
        JavaPackage oldPackage = (JavaPackage) iter.next();
        Resource referenced[] = findReferencedResources(oldPackage.getName());
        for (int i = 0; i < referenced.length; i++) {
            List imports = referenced[i].getImports();
            for (Iterator it = imports.iterator(); it.hasNext();) {
                Import imp = (Import) it.next();
                NamedElement el = imp.getImportedElement();
                if (el.equals(oldPackage)) {
                    elements.add(new RemoveImport(imp));
                }
            }
        }
        }
        
        for (Iterator i = resources.iterator(); i.hasNext();) {
            Resource r = (Resource) i.next();
            String targetPkgName = isPackageRename ? newPackageName : getPackageName(classPath, (FileObject) targetFileMap.get(r));
            
            for (Iterator importsIterator = r.getImports().iterator(); importsIterator.hasNext();) {
                Import imp = (Import) importsIterator.next();
                NamedElement ne = imp.getImportedElement();
                if (ne instanceof UnresolvedClass)
                    continue;
                if (ne instanceof JavaClass)
                    ne = (NamedElement) ((NamedElement) ne.refImmediateComposite()).refImmediateComposite();
                if (!(ne instanceof JavaPackage))
                    continue;
                if (ne.getName().equals(targetPkgName)) {
                    elements.add(new RemoveImport(imp));
                }
            }
        }
    }
    
    private static Resource[] findReferencedResources(String packageName) {
        if ("".equals(packageName)) {
            return new Resource[0];
        }
        StringTokenizer tokenizer = new StringTokenizer(packageName, "."); //NOI18N
        String part = tokenizer.nextToken();
        List result = new ArrayList(Arrays.asList((Object[]) ClassIndex.findResourcesForIdentifier(part)));

        while (tokenizer.hasMoreTokens()) {
            part = tokenizer.nextToken();
            result.retainAll(Arrays.asList((Object[]) ClassIndex.findResourcesForIdentifier(part)));
        }
        return (Resource[]) result.toArray(new Resource[result.size()]);
    }


    private static String getPackageName(ClassPath cp, FileObject f) {
        return cp.getResourceName(f, '.', false);
    }
    
    private boolean isFullName(MultipartId id) {
        while (id != null) {
            if (id.getElement() instanceof JavaPackage)
                return true;
            id = id.getParent();
        }
        return false;
    }
    
    private Problem checkUsedElements(Problem problem) {
        for (Iterator iter = allClasses.iterator(); iter.hasNext();) {
            JavaClass jc = (JavaClass) iter.next(); // [TODO] anonymous classes
            problem = checkUsedElements(jc, new HashSet(), problem);
        }
        return problem;
    }
    
    private Problem checkUsedElements(Element elem, Set markedResources, Problem problem) {
        List elements = elem.getChildren();
        if (elem instanceof ElementReference) {
            Object tmp = ((ElementReference) elem).getElement();
            if (tmp != null) elements.add(tmp);
        }
        Iterator iter = elements.iterator();
        while (iter.hasNext()) {
            Object el = iter.next();
            if ((el instanceof JavaClass) || (el instanceof Feature && !(elem instanceof Feature)))
                continue;
            if (el instanceof ElementReference) {
                NamedElement namedElem = ((ElementReference) el).getElement();

                //workaround for #45796 .. is it necessary to handle arrays differently?
                while(namedElem instanceof Array) {
                    namedElem = ((Array) namedElem).getType();
                }
                if (namedElem instanceof Feature) {
                    Feature f = (Feature) namedElem;
                    Resource res = getResource(f);
                    if (res != null && !resources.contains(res) && !markedResources.contains(res)) {
                        JavaPackage pkg = (JavaPackage) res.refImmediateComposite();
                        
                        boolean accessesOriginalPackage = false;
                        for (Iterator i = resources.iterator(); i.hasNext();) {
                            Resource resource = (Resource) i.next();
                            JavaPackage sourcePackage = (JavaPackage) resource.refImmediateComposite();
                            if (sourcePackage == pkg) {
                                accessesOriginalPackageMap.put(resource, Boolean.TRUE);
                                accessesOriginalPackage = true;
                            }
                        }

//                        if (!accessesOriginalPackage)
//                            continue;
                        
                        int modifiers = f.getModifiers();
                        if (!(f instanceof Initializer) && ((modifiers & Modifier.PUBLIC) == 0) &&
                            ((modifiers & Modifier.PRIVATE) == 0)) {
                            markedResources.add(res);
                            String modStr = (modifiers & Modifier.PROTECTED) != 0 ? getString ("LBL_Protected") : getString ("LBL_PackagePrivate"); // NOI18N
                            Problem p;
                            if (f instanceof JavaClass) {
                                p = new Problem (false,
                                    new MessageFormat(getString("ERR_AccessesPackagePrivateClass")).format ( // NOI18N
                                        new Object[] {
                                            getEnclosingClass((Element)el).getName(),
                                            modStr,
                                            f.getName ()
                                        }
                                    )
                                );
                            } else if (f instanceof Constructor) {
                                p = new Problem (false,
                                    new MessageFormat(getString("ERR_AccessesPackagePrivateConstructor")).format ( // NOI18N
                                        new Object[] {
                                            getEnclosingClass((Element)el).getName(),
                                            modStr,
                                            ((JavaClass)f.getDeclaringClass()).getName()
                                        }
                                    )
                                );
                            } else {
                                p = new Problem (false,
                                    new MessageFormat(getString("ERR_AccessesPackagePrivateFeature")).format ( // NOI18N
                                        new Object[] {
                                            getEnclosingClass((Element)el).getName(),
                                            modStr,
                                            getFeatureKindName(f),
                                            f.getName (),
                                            ((JavaClass)f.getDeclaringClass()).getName()
                                        }
                                    )
                                );
                            }
                            p.setNext(problem);
                            problem = p;
                        } // if
                    } // if
                } // if
            } // if
            if (!(el instanceof TypeReference))
                problem = checkUsedElements((Element) el, markedResources, problem);
        } // while
        return problem;
    }
    
    private void checkWhereUsed(Collection elements) {
        for (Iterator i = resources.iterator(); i.hasNext();) {
            Resource resource = (Resource) i.next();
            JavaClass[] sourceClasses = (JavaClass[]) sourceClassesMap.get(resource);
            for (int x = 0; x < sourceClasses.length; x++) {
                checkWhereUsed(elements, sourceClasses[x], resource);
            }
        }
    }
    
    private Element getImport(Element e) {
        Element orig = e;
        while (e instanceof MultipartId) {
            e = (Element) e.refImmediateComposite();
        }
        if (e instanceof Import) {
            return e;
        } else {
            return orig;
        }
    }
    
    private void checkWhereUsed(Collection elements, JavaClass jc, Resource r) {
        String targetPkgName = isPackageRename ? newPackageName : getPackageName(classPath, (FileObject) targetFileMap.get(r));
        JavaPackage targetPackage = isPackageRename ? null : findJavaPackage(classPath, (FileObject) targetFileMap.get(r));
        Collection users = jc.getReferences();
        boolean movingToDefaultPackage = ((Boolean) movingToDefaultPackageMap.get(r)).booleanValue();
        for (referencesIterator = users.iterator(); referencesIterator.hasNext();) {
            if (cancelRequest) {
                return ;
            }
            Element elem = getImport((Element) referencesIterator.next());
            if (elem instanceof MultipartId) {
                if (isFullName((MultipartId)elem)) {
                    elements.add(new RenameFullNameElement(jc, (MultipartId)elem, targetPkgName));
                } else {
                    // check if an import is required to be added
                    Resource res = getResource(elem);
                    JavaPackage resPkg = (JavaPackage) res.refImmediateComposite();
                    Set checkedSources = (Set) checkedSourcesMap.get(r);
                    if (!movingToDefaultPackage && !resources.contains(res) && !checkedSources.contains(res)) {
                        checkedSources.add(res);
                        if ((isPackageRename || resPkg != targetPackage) && !containsImport(res, jc.getName())) {
                            elements.add(new InsertImport(res, targetPkgName + '.' + jc.getSimpleName(), true));
                        }
                    }
                }
            } else if (elem instanceof Import) {
                if (movingToDefaultPackage) {
                    elements.add(new RemoveImport((Import)elem));
                } else {
                    MultipartId id = ((Import) elem).getIdentifier();
                    if (((Import) elem).isStatic()) {
                        NamedElement el = id.getElement();
                        if (el != null) {
                            if (el instanceof Field || el instanceof Method) {
                                id = id.getParent();
                            }
                        } else {
                            continue;
                        }
                    }
                    elements.add(new RenameFullNameElement(jc, id, targetPkgName));
                }
            }
        }
    }
            
    private Resource getResource(Element elem) {
        //workaround .. why refImmediateComposite is null for Parameterized Type?
        if (elem instanceof Type) { 
            elem = TypeClassImpl.getRealType((Type) elem);
        }
        while (elem != null && !(elem instanceof Resource))
            elem = (Element) elem.refImmediateComposite();
        return (Resource)elem;
    }

    private JavaClass getEnclosingClass(Element elem) {
        while (elem != null && !(elem instanceof JavaClass))
            elem = (Element) elem.refImmediateComposite();
        return (JavaClass)elem;
    }
    
    private boolean containsImport(Resource res, JavaClass jc) {
        JavaPackage pkg = (JavaPackage) getResource(jc).refImmediateComposite();
        for (Iterator iter = res.getImports().iterator(); iter.hasNext();) {
            Import imp = (Import) iter.next();
            NamedElement elem = imp.getImportedElement();
            if (elem == jc || elem == pkg)
                return true;
        }
        return false;
    }

    private boolean containsImport(Resource res, String impName) {
        for (Iterator iter = res.getImports().iterator(); iter.hasNext();) {
            Import imp = (Import) iter.next();
            if (impName.equals(imp.getName()))            
                return true;
        }
        return false;
    }
    
    private Problem checkAccessesMyFeature(Problem problem) {
        for (Iterator iter = allClasses.iterator(); iter.hasNext();) {
            JavaClass jc = (JavaClass) iter.next();
            problem = checkAccessesMyFeature(problem, jc);
        }
        return problem;
    }
    
    private Problem checkAccessesMyFeature(Problem problem, JavaClass jc) {
        boolean classChecked = false;
        Set set = new HashSet();
        Set accessedFeatures = new HashSet();
        for (Iterator iter = jc.getFeatures().iterator(); iter.hasNext() || !classChecked;) {
            Feature f;
            if (!classChecked) {
                f = jc;
                classChecked = true;
            } else {        
                f = (Feature) iter.next();
                if (f instanceof JavaClass)
                    continue;
            }
            int modifiers = f.getModifiers();
            if (!(f instanceof Initializer) && ((modifiers & Modifier.PUBLIC) == 0) && ((modifiers & Modifier.PRIVATE) == 0)) {
                boolean isProtected = (modifiers & Modifier.PROTECTED) != 0;
                Collection users = f.getReferences();
                for (referencesIterator = users.iterator(); referencesIterator.hasNext();) {
                    if (cancelRequest) {
                        return null;
                    }
                    Element elem = (Element) referencesIterator.next();
                    Resource res = (Resource) getResource(elem);
                    String modStr = (modifiers & Modifier.PROTECTED) != 0 ? getString ("LBL_Protected") : getString ("LBL_PackagePrivate"); // NOI18N
                    if (!resources.contains(res) && set.add(res) && accessedFeatures.add(f)) {
                        JavaPackage pkg = (JavaPackage) res.refImmediateComposite();
                        boolean cont = false;
                        for (Iterator i = resources.iterator(); i.hasNext();) {
                            JavaPackage sourcePackage = (JavaPackage) ((Resource)i.next()).refImmediateComposite();
                            if (pkg != sourcePackage) {
                                cont = true;
                            }
                        }
                        if (cont)
                            continue;
                        Problem p;
                        if (f instanceof JavaClass) {
                            p = new Problem (false,
                            new MessageFormat(getString("ERR_AccessesPackagePrivateClass")).format ( // NOI18N
                                new Object[] {
                                    getEnclosingClass(elem).getName(),
                                    modStr,
                                    f.getName ()
                                }
                            ));
                        } else if (f instanceof Constructor) {
                            p = new Problem (false,
                                new MessageFormat(getString("ERR_AccessesPackagePrivateConstructor")).format ( // NOI18N
                                    new Object[] {
                                        getEnclosingClass(elem).getName(),
                                        modStr,
                                        ((JavaClass)f.getDeclaringClass()).getName()
                                    }
                                )
                            );
                        } else {
                            p = new Problem (false,
                            new MessageFormat(getString("ERR_AccessesPackagePrivateFeature")).format ( // NOI18N
                                new Object[] {
                                    getEnclosingClass(elem).getName(),
                                    modStr,
                                    getFeatureKindName(f),
                                    f.getName (),
                                    ((JavaClass) f.getDeclaringClass ()).getName ()
                                }
                            ));
                        }
                        p.setNext(problem);
                        problem = p;
                    }
                }
            } // if
        } // for
        return problem;
    }

    private boolean isAccessedByOriginalPackage(Resource r) {
        JavaClass[] sourceClasses  = (JavaClass[]) sourceClassesMap.get(r);
        JavaPackage sourcePackage = (JavaPackage) r.refImmediateComposite();

        for (int x = 0; x < sourceClasses.length; x++) {
            for (referencesIterator = sourceClasses[x].getReferences().iterator(); referencesIterator.hasNext();) {
                if (cancelRequest)
                    return false;
                Element elem = (Element) referencesIterator.next();
                Resource res = (Resource) getResource(elem);
                JavaPackage pkg = (JavaPackage) res.refImmediateComposite();
                if (/*pkg == sourcePackage &&*/ !resources.contains(res))
                    return true;
            }
        }
        return false;
    }
    
    private String getFeatureKindName(Feature f) {
        String featureKind;
        if (f instanceof Method) {
            featureKind = getString ("LBL_Method"); // NOI18N
        } else if (f instanceof Field) {
            featureKind = getString ("LBL_Field"); // NOI18N
        } else if (f instanceof Constructor) {
            featureKind = getString ("LBL_Constructor"); // NOI18N
        } else if (f instanceof JavaClass) {
            featureKind = getString ("LBL_Class"); // NOI18N
        } else {
            featureKind = "???"; // NOI18N
        }
        return featureKind;
    }
    
    private void collectAllClasses (Collection classes, JavaClass jc) {
        classes.add (jc);
        Iterator iter = jc.getFeatures().iterator ();
        while (iter.hasNext ()) {
            Object obj = iter.next();
            if (obj instanceof JavaClass)
                collectAllClasses (classes, (JavaClass) obj);
        }
    }
    
    public Problem checkParameters(FileObject targetFile) {
        //implement fast checks
        return null;
    }
    
    private FileObject target;
    public Problem setParameters (FileObject target) {
        Problem p = null;
        this.target = target;
        fireProgressListenerStart(PARAMETERS_CHECK, 2);
        try {
            for (Iterator i = resources.iterator(); i.hasNext();) {
                Resource r = (Resource) i.next();
                targetFileMap.put(r, target != null || isPackageRename ? target : ((DataObject) sourceObjectsMap.get(r)).getFolder().getPrimaryFile());
            }

            for (Iterator i = resources.iterator(); i.hasNext();) {
                Resource r = (Resource) i.next(); 
                FileObject targetFile = (FileObject) targetFileMap.get(r);
            
                String pkgName = null;
                if (!isPackageRename && !targetFile.canWrite()) {
                    return new Problem(true, new MessageFormat(getString("ERR_PackageIsReadOnly")).format( // NOI18N
                    new Object[] {getPackageName(classPath, targetFile)}
                    ));
                }
                if (!isPackageRename) {
                    this.movingToDefaultPackageMap.put(r, Boolean.valueOf(targetFile.equals(classPath.findOwnerRoot(targetFile))));
                    pkgName = getPackageName(classPath, targetFile);
                } else {
                    this.movingToDefaultPackageMap.put(r, Boolean.valueOf("".equals(newPackageName)));
                    pkgName = newPackageName;
                }
            
                if (pkgName == null) {
                    pkgName = ""; // NOI18N
                } else if (pkgName.length() > 0) {
                    pkgName = pkgName + '.';
                }
                //targetPrefix = pkgName;
                fireProgressListenerStep();
                
                JavaClass[] sourceClasses = (JavaClass[]) sourceClassesMap.get(r);
                String[] names = new String [sourceClasses.length];
                for (int x = 0; x < names.length; x++) {
                    names [x] = sourceClasses [x].getName();
                }
                
                if (!isPackageRename && !invokedAfterDOMove) {
                    FileObject movedFile = JavaMetamodel.getManager().getDataObject(r).getPrimaryFile();
                    String fileName = movedFile.getName();
                    FileObject[] children = targetFile.getChildren();
                    for (int x = 0; x < children.length; x++) {
                        if (children[x].getName().equals(fileName) && "java".equals(children[x].getExt()) && !children[x].equals(movedFile)) { //NOI18N
                            return new Problem(true, new MessageFormat(
                                getString("ERR_ClassToMoveClashes")).format(new Object[] {fileName} // NOI18N
                            ));
                        }
                    } // for
                    
                    /*
                    JavaPackage pkg = findJavaPackage(classPath, targetFile);
                    if (pkg != null) {
                        Iterator it = pkg.getResources().iterator();
                        while (it.hasNext()) {
                            Resource resource = (Resource) it.next();
                            Iterator iter = resource.getClassifiers().iterator();
                            while (iter.hasNext()) {
                                Object obj = iter.next();
                                if (!(obj instanceof JavaClass)) {
                                    continue;
                                }
                                JavaClass cls = (JavaClass) obj;
                                for (int x = 0; x < names.length; x++) {
                                    if (cls.getName().equals(names[x])) {
                                        return new Problem(true, new MessageFormat(
                                        getString("ERR_ClassToMoveClashes")).format(new Object[] {names[x]} // NOI18N
                                        ));
                                    } // if
                                } // for
                            } // while
                        } // while
                    } // if
                     */
                }
                
                if (!isPackageRename) {
                boolean accessedByOriginalPackage = ((Boolean) accessedByOriginalPackageMap.get(r)).booleanValue();
                boolean movingToDefaultPackage = ((Boolean) movingToDefaultPackageMap.get(r)).booleanValue();
                if (p==null && accessedByOriginalPackage && movingToDefaultPackage) {
                    p= new Problem(false, getString("ERR_MovingClassToDefaultPackage")); // NOI18N
                }
                } else {
                     if (p==null && "".equals(newPackageName)) {
                        p= new Problem(false, getString("ERR_MovingClassToDefaultPackage")); // NOI18N
                     }
                }
                if (r.getPackageName().equals(getPackageName(classPath, targetFile))) {
                    return new Problem(true, getString("ERR_CannotMoveIntoSamePackage"));
                }
            }

            fireProgressListenerStep();
        } finally {
            fireProgressListenerStop();
        }
        return p;
    }
    
    private boolean isPackageRename = false;
    private String newPackageName;
    public Problem setParameters(String newName) {
//        ClassPath thisProjectCP = ClassPath.getClassPath(folder, ClassPath.SOURCE);
//        FileObject f = thisProjectCP.findResource(newName.replace('.','/'));
//        if (f == null) {
//            try {
//                f = FileUtil.createFolder(thisProjectCP.findOwnerRoot(folder), newName.replace('.','/'));
//            } catch (IOException e) {
//                
//            }
//        }
        Problem p = checkParameters(newName);
        if (p!=null) {
            return p;
        }
        isPackageRename = true;
        newPackageName = newName;
        return setParameters((FileObject) null);
    }
    
    public Problem checkParameters(String newName) {
        if (!isValidPackageName(newName)) {
            String s = getString("ERR_InvalidPackage");
            String msg = new MessageFormat(s).format(
                new Object[] {newName}
            );
            return new Problem(true, msg);
        }
        ClassPath thisProjectCP = ClassPath.getClassPath(folder, ClassPath.SOURCE);
        FileObject f = thisProjectCP.findResource(newName.replace('.','/'));
        if (f!=null && ((f.isFolder() && !CheckUtils.isFolderEmpty(f)) || !f.isFolder())) {
            String msg = new MessageFormat(getString("ERR_PackageExists")).format(
                new Object[] {newName}
            );
            return new Problem(true, msg);
        }
        return null;
    }
    
    private static boolean isValidPackageName(String name) {
        StringTokenizer tokenizer = new StringTokenizer(name, "."); // NOI18N
        while (tokenizer.hasMoreTokens()) {
            if (!Utilities.isJavaIdentifier(tokenizer.nextToken())) {
                return false;
            }
        }
        return true;
    }
    
    static final JavaPackage findJavaPackage (ClassPath cp, FileObject file) {
        JavaMetamodel manager = JavaMetamodel.getManager();
        FileObject root = cp.findOwnerRoot(file);
        JavaModelPackage jmp = manager.resolveJavaExtent(root);
        JavaPackageClass proxy = jmp.getJavaPackage();
        return proxy.resolvePackage(getPackageName(cp, file));
    }
    
    static final String getString(String key) {
        return NbBundle.getMessage(MoveClassRefactoring.class, key);
    }
    
    // --------------------------------------------------------------------------
    
    // MoveClass ................................................................
    class MoveClass implements RefactoringElement, ExternalChange {
        
        private DataObject source;
        private FileObject target;
        private FileObject oldTarget = null;
        private JavaClass[] sourceClasses;
        private PositionBounds bounds = null;
        
        private DataObject copiedObject = null;
        
        private boolean enabled = true;
        private FileObject targetRoot = null;
        private String packageName = null;
        private boolean deleteSourceFolderAfterMove = false;
        
        public MoveClass (DataObject source, FileObject target, JavaClass[] sourceClasses) {
            this.source = source;
            this.target = target;
            this.sourceClasses = sourceClasses;
        }
        
        public MoveClass (DataObject source, FileObject targetRoot, String packageName,  JavaClass[] sourceClasses) {
            this.source = source;
            this.targetRoot = targetRoot;
            this.sourceClasses = sourceClasses;
            this.packageName = packageName;
            deleteSourceFolderAfterMove = true;
        }
        
        public String getText() {
            return getDisplayText ();
        }
    
        public String getDisplayText() {
            String name;
            if (target == null) {
                name = packageName;
            } else {
                name = getPackageName(classPath, target);
            }
            if ("".equals(name)) {
                name = getString ("LBL_DefaultPackage"); // NOI18N 
            }
            if (sourceClasses == null) {
                return new MessageFormat(MoveClassRefactoring.getString("LBL_MoveObject")).format( // NOI18N
                    new Object[] {source.getNodeDelegate().getDisplayName(), name}
                );
                
            } else {
                return new MessageFormat(MoveClassRefactoring.getString("LBL_MoveClass")).format( // NOI18N
                    new Object[] {name}
                );
            }
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public Element getJavaElement() {
            if (sourceClasses == null) 
                return null;
            return (Element) sourceClasses[0].refImmediateComposite();
        }

        public PositionBounds getPosition() {
            if (sourceClasses == null) 
                return null;
            if (bounds == null) {
                bounds = NbAbstractRefactoring.getPositionBounds (sourceClasses[0]);
            }
            return bounds;
        }

        public int getStatus() {
            return RefactoringElement.NORMAL;
        }
        
        public void performChange() {
            String name = target==null ? packageName : getPackageName(classPath, target);
            if (sourceClasses != null) 
                JavaMetamodel.getManager().getResource(source.getPrimaryFile()).setPackageName(name);
            if (target==null || !target.equals(source.getPrimaryFile().getParent())) {
                JavaMetamodel.getManager().registerExtChange(this);
            }
        }
        
        private void doMove() {    
            RefactoringOperationListener.removeOperationalListener();
            try {
                if (target == null) {
                    target = FileUtil.createFolder(targetRoot, packageName.replace('.','/'));
                } else if (!target.isValid()) {
                    target = FileUtil.createFolder(target.getFileSystem().getRoot(), target.getPath());
                }
                    
                DataFolder folder = DataFolder.findFolder(target);
                DataFolder sourceFolder = DataFolder.findFolder(source.getPrimaryFile ().getParent ());
                oldTarget = source.getPrimaryFile ().getParent ();
                source.move(folder);
                
                if (deleteSourceFolderAfterMove) {
                    while (sourceFolder.getChildren().length == 0) {
                        DataFolder temp = sourceFolder.getFolder();
                        sourceFolder.delete();
                        sourceFolder = temp;
                    }
                }
                JavaMetamodel.getManager().addModified(source);
                //movedSource = source;
            } catch (IOException e) {
                System.out.println(e);
                e.printStackTrace ();
            }
            RefactoringOperationListener.addOperationalListener();
        }
        
        public void performExternalChange() {
            try {
                if (target == null) {
                    target = FileUtil.createFolder(targetRoot, packageName.replace('.','/'));
                }
            } catch (IOException e) {
                System.out.println(e);
                e.printStackTrace();
            }
            doMove();
        }
        
        public void undoExternalChange() {
            if (oldTarget == null) return;
            FileObject temp = target;
            target = oldTarget;
            oldTarget = temp; 
            doMove();
            target = temp; 
        } 
               
        
    } // MoveClass ..............................................................

    // InsertImport .............................................................
    static class InsertImport implements RefactoringElement {
        
        protected ImportClass proxy;
        protected Resource source;
        protected String newName;
        protected boolean isNamed;
        private PositionBounds bounds = null;
        
        protected Import addedImport = null;
        
        private boolean enabled = true;
        
        public InsertImport (Resource source, String newName, boolean isNamed) {
            this.source = source;
            this.newName = newName;
            this.isNamed = isNamed;
            proxy = ((JavaModelPackage) source.refOutermostPackage ()).getImport ();
        }
        
        public String getText() {
            return getDisplayText ();
        }
    
        public String getDisplayText() {
            return new MessageFormat (MoveClassRefactoring.getString("LBL_InsertImport")).format ( // NOI18N
                new Object[] {newName}
            );
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public void performChange() {
            addedImport = proxy.createImport (newName, null, false, !isNamed);
            source.getImports ().add (addedImport);
        }

        public void undoChange() {
            source.getImports ().remove(addedImport);
        }

        public Element getJavaElement() {
            return source;
        }

        public PositionBounds getPosition() {
            if (bounds == null) {
                bounds = NbAbstractRefactoring.getPositionBounds (source);
            }
            return bounds;
        }

        public int getStatus() {
            return RefactoringElement.NORMAL;
        }
        
    } // InsertImport ...........................................................
    
    // RemoveImport .............................................................
    static class RemoveImport implements RefactoringElement {
        
        private Import imp;
        private Resource res;
        private boolean enabled = true;
        private PositionBounds bounds = null;
        private int status;
        
        public RemoveImport (Import imp) {
            this.imp = imp;
            this.res = (Resource)imp.refImmediateComposite();
            if (JavaMetamodel.getManager().isElementGuarded(imp)) {
                status = RefactoringElement.GUARDED;
            } else {
                status = RefactoringElement.NORMAL;
            }
        }
                
        public String getText() {
            return getDisplayText ();
        }
    
        public String getDisplayText() {
            return new MessageFormat (MoveClassRefactoring.getString("LBL_RemoveImport")).format ( // NOI18N
                new Object[] {imp.getName()}
            );
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public void performChange() {
            res.getImports().remove(imp);
        }

        public void undoChange() {
            res.getImports().add(imp);
        }

        public Element getJavaElement() {
            return res;
        }

        public PositionBounds getPosition() {
            if (bounds == null) {
                bounds = NbAbstractRefactoring.getPositionBounds (res);
            }
            return bounds;
        }

        public int getStatus() {
            return status;
        }

    } // RemoveImport ...........................................................
    
}    
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.