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-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

/*
 * UsageFinder.java
 *
 * Created on 06 January 2004, 11:44
 */

package org.netbeans.modules.javacore.jmiimpl.javamodel;

import java.util.*;
import org.netbeans.jmi.javamodel.*;
import org.netbeans.modules.javacore.JMManager;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.modules.javacore.internalapi.ProgressSupport;
import org.openide.ErrorManager;
import org.openide.util.Cancellable;

/**
 *
 * @author  Jan Becicka
 */
public class UsageFinder {
    
    private NamedElement what;
    private ElementNavigator navigator;
    private Collection usages;
    private static final int MAX_COUNT = 30;
    private Set declaringClasses;
    private boolean overriders = false;
    private boolean findUsages = true;
    
    /** Creates a new instance of UsageFinder */
    public UsageFinder(NamedElement what) {
        if (what instanceof ParameterizedType) {
            this.what = convert(getRealClassDefinition((ParameterizedType) what));
        } else {
            this.what = convert(what);
        }
    }
    
    private static List getParameters(CallableFeature f) {
        List params = new ArrayList();
        for (Iterator i = f.getParameters().iterator(); i.hasNext(); params.add(convert(TypeClassImpl.getRealType(((Parameter)i.next()).getType()))));
        return params;
    }
    
    private static NamedElement convert(NamedElement what) {
        if (what instanceof TypeParameter) {
            return what;
        }
        if (what instanceof JavaClass) {
            return convert((JavaClass) what);
        }

        NamedElement convertedElement = null;
        
        if (what instanceof ClassMember) {
            ClassDefinition cls = ((ClassMember) what).getDeclaringClass();
            if (cls instanceof JavaClass) {
                JavaClass clazz = (JavaClass) convert(cls);
                if (clazz.equals(cls)) {
                    return what;
                }

                if (what instanceof Field) {
                    convertedElement = clazz.getField(what.getName(), false);
                } else {
                    if (what instanceof Method) {
                        convertedElement = clazz.getMethod(what.getName(), getParameters((CallableFeature) what), false);
                    } else if (what instanceof Constructor) {
                        convertedElement = clazz.getConstructor(getParameters((CallableFeature) what), false);
                    }
                }
            } 
        }
        return convertedElement == null ? what:convertedElement ;
    }
    
    private static Type convert(Type clazz) {
        return JavaMetamodel.getManager().getDefaultExtent().getType().resolve(clazz.getName());
    }
    
    /**
     * specific contructor for method
     * @param method method for search
     * @param findUsages find usages of methods
     * @param fromBaseClass find all occurrences including superclass
     * @param overriders get Overriding Methods
     */
    public UsageFinder(CallableFeature method, boolean findUsages, boolean fromBaseClass, boolean overriders) {
        this(method);
        this.overriders = overriders;
        this.findUsages = findUsages;
        declaringClasses = new HashSet();
        ClassDefinition clazz = method.getDeclaringClass();
        declaringClasses.add(getRealClassDefinition(clazz));
        List argTypes = new ArrayList();
        for (Iterator i = method.getParameters().iterator(); i.hasNext(); argTypes.add(TypeClassImpl.getRealType(((Parameter)i.next()).getType())));
        
        if (fromBaseClass) {
            LinkedList q = new LinkedList();
            q.add(clazz);
            while (!q.isEmpty()) {
                clazz = (ClassDefinition) q.removeFirst();
                CallableFeature callFeature = null;
                if (method instanceof Method) 
                    callFeature = clazz.getMethod(method.getName(), argTypes, false);
                else
                    callFeature = clazz.getConstructor(argTypes, false);
                if (callFeature != null) {
                    declaringClasses.add(getRealClassDefinition(clazz));
                }
                q.addAll(clazz.getInterfaces());
                clazz = clazz.getSuperClass();
                if (clazz!=null) {
                    q.add(clazz);
                }
            }
        }
    }
    
    private ClassDefinition getRealClassDefinition(ClassDefinition cls) {
        return (ClassDefinition) TypeClassImpl.getRealType(cls);
    }
    
    private Collection getUsers(MetadataElement where) {
        usages = new ArrayList();
        List l = new ArrayList(1);
        l.add(where);
        getUsers(l);
        return usages;
    }
    
    public Collection getUsers(Resource res[]) {
        return new LazyCollection(res);
    }
    
    private void getUsers(Collection elements) {
        if (elements == null || elements.isEmpty())
            return;
        
        for (Iterator iter = elements.iterator(); iter.hasNext();) {
            MetadataElement el = (MetadataElement) iter.next();
            if ((el instanceof Resource) || navigator.containsIdentifierIn(el)) {
                if (isMatch(what, el)) {
                    usages.add(el);
                }
                getUsers(el.getChildren());
            }
        }
    }
    
    private boolean isMatch(Element what, Element r) {
        Element ref = r;
        if (findUsages) {
            if (ref instanceof ElementReference) {
                ref = ((ElementReference) r).getElement();
            } else {
                if (!overriders) {
                    return false; 
                }
            }
        }

        if (!(what instanceof Method)) {
            if (ref instanceof ParameterizedType) {
                ref = getRealClassDefinition((ParameterizedType) ref);
            }
            return what.equals(ref);
        }

//        if (!overriders) {
//            if (ref instanceof Method)
//                return false;
//        }

        if (!(ref instanceof Method)) {
            return false;
        }
        
        if (!overriders && what.equals(ref)) {
            return true;
        }
        
        Method m = (Method) ref;
        if (m.signatureEquals((Method) what)) {
            ClassDefinition collectedClass, declaringClass = getRealClassDefinition(m.getDeclaringClass());
            for (Iterator i = declaringClasses.iterator(); i.hasNext();) {
                collectedClass = (ClassDefinition) i.next();
                if (declaringClass.isSubTypeOf(collectedClass)) {
                    return true;
                }
            }
        }
        return false;
    }

    private class LazyCollection extends AbstractCollection {
        Resource res[];
        
        public LazyCollection(Resource res[]) {
            this.res=res;
        }
        
        public Iterator iterator() {
            return new LazyIterator(res);
        }

        public int size() {
            int size = 0;
            for (Iterator i = iterator(); i.hasNext(); i.next(), size++ );
            return size;
        }
    }
    
    private class LazyIterator implements Iterator, Cancellable {
        
        Resource res[];
        Collection currentUsages = Collections.EMPTY_LIST;
        Iterator inner;
        int currentIndex;
        Object next;
        boolean hasNext;
        float step;
        int last;
        ProgressSupport progressSupport;
        private boolean cancelRequest;
        
        LazyIterator(Resource[] res) {
            this.res = res;
            inner = currentUsages.iterator();
            currentIndex = -1;
            hasNext = true;
            
            step = 1;
            if (res.length > MAX_COUNT) {
                step = (float) MAX_COUNT / res.length;
            }
            last = 0;
        
            progressSupport = org.netbeans.modules.javacore.internalapi.JavaMetamodel.getManager().getProgressSupport();
        }
                
        public void remove() {
            throw new UnsupportedOperationException();
        }
        
        public Object next() {
            if (next==null) {
                findNext();
            }
            Object result = next;
            next = null;
            return result;
        }
        
        private void findNext() {
            if (!hasNext) {
                throw new NoSuchElementException();
            }
            while (next==null && hasNext == true) {
                if (!inner.hasNext()) {
                    if (cancelRequest)
                        return;                    
                    currentIndex++;
                    if (currentIndex == 0) {
                        progressSupport.fireProgressListenerStart(0, Math.min(res.length,MAX_COUNT));
                    }
                    if (currentIndex < res.length) {
                        try {
                            if (!res[currentIndex].getName().endsWith("class")) {
                                navigator = new ElementNavigator(res[currentIndex], what);
                                currentUsages = getUsers((MetadataElement) res[currentIndex]);
                                inner = currentUsages.iterator();
                            }
                        } catch (IllegalArgumentException e) {
                            JMManager.getLog().notify(ErrorManager.INFORMATIONAL, new Exception("Resource " + res[currentIndex].getName() + " is not parsable: " + e.getMessage()));
                        }

                        if (currentIndex*step >= last) {
                            progressSupport.fireProgressListenerStep();
                            last++;
                        }

                    } else {
                        hasNext = false;
                        progressSupport.fireProgressListenerStop();
                    }
                }
                if (inner.hasNext()) {
                    next = inner.next(); 
                }
            }
        }
            
        public boolean hasNext() {
            findNext();
            if (cancelRequest)
                return false;
            return hasNext;
        }
        
        public boolean cancel() {
            cancelRequest = true;
            return true;
        }
    }
}
... 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.