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.
 */

package org.netbeans.modules.javacore;

import java.io.IOException;
import java.util.*;
import javax.swing.text.Position;
import org.netbeans.jmi.javamodel.*;
import org.netbeans.mdr.handlers.BaseObjectHandler;
import org.netbeans.mdr.persistence.StorageException;
import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
import org.netbeans.modules.javacore.jmiimpl.javamodel.*;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.util.NbBundle;

/**
 * TryWrapper can encapsulate block with a try statement
 * @author Jan Becicka
 */
public class TryWrapper {
    
    /**
     * The first element of a selection
     */    
    private Statement fromElement;
    /**
     * The last element of a selection
     */    
    private Statement toElement;
    /**
     * Parent of last and fisrt element
     */    
    private Element commonParent;
    /**
     * element which will be replaced by try statement
     */    
    private Element elementToReplace;
    /**
     * parent of elementToReplace
     */    
    private Element replaceParent;
    
    private JavaModelPackage model;
    private Position retVal;
    
    /**
     * TryWrapper can encapsulate block with a try statement
     * @param fo FileObject where try will be added
     * @param from begin index
     * @param to end index
     */    
    public TryWrapper(FileObject fo, int from, int to) { 
        
        ElementFinder finder = new ElementFinder(org.netbeans.modules.javacore.internalapi.JavaMetamodel.getManager().getResource(fo));
        if (from==to) {
            fromElement=toElement=getStatement(finder.getElementByOffset(from));
        } else {
        fromElement = getStatement(finder.getElementBySelection(from, to, true));
        toElement = getStatement(finder.getElementBySelection(from, to, false));
        }
        
        if (fromElement==null || toElement == null) {
            throw new GeneralException(NbBundle.getMessage(TryWrapper.class, "MSG_CannotEncapsulate"));
        }
        
        commonParent = getCommonParent(fromElement, toElement);
        
        if (commonParent==null) {
            throw new GeneralException(NbBundle.getMessage(TryWrapper.class, "MSG_CannotEncapsulate"));
        }
        try {
            retVal = JavaMetamodel.getManager().getElementPosition(toElement).getEnd().getPosition();  
        } catch (IOException e) { 
        
        }
        model = (JavaModelPackage) fromElement.refOutermostPackage();
    }
    
    /**
     * returns body of try statement
     * @return List of Statements
     */    
    private List getTryBody() {
        
        ArrayList tryBody = new ArrayList();
        if ((commonParent instanceof StatementBlock) && fromElement != commonParent) {
            Iterator i = ((StatementBlock) commonParent).getStatements().iterator();
            boolean add = false;
            while (i.hasNext()) {
                Object nextStatement = i.next();
                if (!add && hasChild((Element) nextStatement, fromElement)) {
                    add = true;
                    elementToReplace = (Element) nextStatement;
                    replaceParent = (Element) elementToReplace.refImmediateComposite();
                }
                if (add) {
                    clearComposite((Element) nextStatement);
                    tryBody.add(nextStatement);
                }
                if (hasChild((Element) nextStatement, toElement))
                    break;
            }
        } else {
            tryBody.add(commonParent);
            elementToReplace = commonParent;
            replaceParent = (Element) elementToReplace.refImmediateComposite();
            clearComposite(commonParent);
        }
        return tryBody;
    }
    
    private int catchesCount;
    public int getCatchesCount() {
        return catchesCount;
    }
    
    private void check(List body, List declaredVariables) {
        Iterator it = body.iterator();
        while (it.hasNext()) {
            Object o = it.next(); 
            if (o instanceof LocalVarDeclaration) {
                LocalVarDeclarationImpl decl = (LocalVarDeclarationImpl) o;
                declaredVariables.addAll(decl.getVariables());
            }
        }
    }
    
    private ExpressionStatement createAssignment(LocalVariable var) {
        VariableAccess access = model.getVariableAccess().createVariableAccess(var.getName(),null, false);
        clearComposite(var.getInitialValue());
        Assignment a = model.getAssignment().createAssignment(access, OperatorEnum.ASSIGN, (Expression) var.getInitialValue());
        ExpressionStatement s = model.getExpressionStatement().createExpressionStatement(a);
        return s;
    }
    
    private LocalVarDeclaration createDeclaration(LocalVariable var) {
        List variables = new ArrayList(1);
        TypeReference ref = (TypeReference) ((MultipartIdImpl) ((LocalVarDeclaration) var.refImmediateComposite()).getTypeName()).duplicate();
        var.setInitialValue(null);
        boolean fina = var.isFinal();
        clearComposite(var);
        variables.add(var);
        LocalVarDeclaration decl = model.getLocalVarDeclaration().createLocalVarDeclaration(fina, ref, variables);
        return decl;
    }
    
    private Set getUsedVariables(List decl, List statements) {
        Set used = new LinkedHashSet();
        LinkedList l = new LinkedList();
        l.addAll(statements);
        while (!l.isEmpty()) {
            Element e = (Element) l.removeFirst();
            if (e instanceof MultipartId) {
                Iterator i = decl.iterator();
                while (i.hasNext()) {
                    LocalVariable var = (LocalVariable) i.next();
                    if (((MultipartId) e).getName().equals(var.getName())) {
                        used.add(var);
                    }
                }
            }
            l.addAll(e.getChildren());
        }
        return used;
    }
    
    /**
     * wrap given selection with a try statement
     */    
    public Position wrap() {
            //try block
            List tryBody = getTryBody();
            List decl = new ArrayList();
            check(tryBody, decl);
            
            StatementBlock tryBlock = model.getStatementBlock().createStatementBlock(tryBody);
            
            List catches = createCatches(getExceptions(tryBlock));

            //empty finally block
            StatementBlock finallyBlock = !catches.isEmpty()?null:model.getStatementBlock().createStatementBlock();
            
            TryStatement tryStatement = model.getTryStatement().createTryStatement(tryBlock, catches, finallyBlock);
            
            if (replaceParent instanceof Feature) {
                ArrayList l = new ArrayList();
                l.add(tryStatement);
                replaceParent.replaceChild(elementToReplace, model.getStatementBlock().createStatementBlock(l));
            } else {
                List ll = new ArrayList();
                ll.addAll(replaceParent.getChildren());
                ll.remove(elementToReplace);
                replaceParent.replaceChild(elementToReplace, tryStatement);
                tryBody.remove(elementToReplace);
                for (Iterator i = tryBody.iterator(); i.hasNext() ; ) {
                    Element e = (Element) i.next();
                    replaceParent.replaceChild(e, null);
                    ll.remove(e);
            }
                Set l = getUsedVariables(decl, ll); 
                System.out.println(l); 
                List body = ((StatementBlock) replaceParent).getStatements();
                int index = body.indexOf(tryStatement);
                body.addAll(index, convert(l, tryBlock)); 
    }
            catchesCount = catches.size() + (finallyBlock == null ? 0 : 1);
            return retVal; 
    }
    
    private List convert(Set l, StatementBlock b) {
        List decl = new ArrayList();
        Iterator i = l.iterator();
        while (i.hasNext()) {
            LocalVariable var = (LocalVariable) i.next();
            LocalVarDeclaration parent = (LocalVarDeclaration) var.refImmediateComposite();
            //var.setTypeName(parent.getTypeName());
            //clearComposite(var);
            ExpressionStatement a = createAssignment(var);
            b.replaceChild(parent, a);
            
            decl.add(createDeclaration(var));
        }
        return decl;
    }
    
    
    
    /**
     * creates catch statements from List of Exception names
     * @param ex List of ElementReferences
     * @return List of Catch statements
     */    
    private List createCatches(Collection ex) {
        ArrayList catches = new ArrayList();
        for (Iterator i = ex.iterator(); i.hasNext();) {
            TypeReference e = (TypeReference) i.next();
            catches.add(model.getCatch().createCatch(model.getParameter().createParameter("e", null, false, e, 0, false), model.getStatementBlock().createStatementBlock())); // NOI18N
        }
        return catches;
    }
    
    /**
     *
     * @param b Statement block to search
     * @return Exception names of all callable features in statement blcok
     */    
    private Collection getExceptions(StatementBlock b) {
        Set l = new LinkedHashSet();
        LinkedList list = new LinkedList(b.getStatements());
        while (!list.isEmpty()) {
            MetadataElement e = (MetadataElement) list.removeFirst();
            if (e instanceof Invocation) {
                Element callable = ((Invocation) e).getElement();
                if (callable!=null && callable instanceof CallableFeature) {
                    l.addAll(((CallableFeature) callable).getExceptions());
                }
            }
            list.addAll(e.getChildren());
        }
        return createExceptions(l);
    }
    
    private Collection createExceptions(Set exceptions) {
        Collection result = new ArrayList();
        for (Iterator i = exceptions.iterator(); i.hasNext();) {
            JavaClass c = (JavaClass) i.next();
            result.add(model.getMultipartId().createMultipartId(c.getName(), null, null));
        }
        return result;
    }
    
    /**
     * Clear composite of given Element
     * @param el
     */    
    private void clearComposite(Element el) {
        if (el==null)
            return ;
        try {
            ((DeferredObject) ((BaseObjectHandler) el)._getDelegate()).clearComposite();
        } catch (StorageException e) {
            throw (GeneralException) ErrorManager.getDefault().annotate(new GeneralException(e.getMessage()), e);
        }
    }
    
    /**
     *
     * @param fromElement
     * @param toElement
     * @return Return common parent of fromElement and toElement
     */    
    private Element getCommonParent(Element fromElement, Element toElement) {
        HashSet parents = new HashSet();
        
        Element e = fromElement;
        do {
            parents.add(e);
            e = (Element) e.refImmediateComposite();
        } while (!(e instanceof Feature) && e != null);
        
        e = toElement;
        do {
            if (parents.contains(e))
                break;
            e = (Element) e.refImmediateComposite();
        } while (!(e instanceof Feature)&& e != null);
        
        return getStatement(e);
    }
    
    /**
     *
     * @param who returns true if child is a child of who (recursively)
     * @param child
     * @return
     */    
    private boolean hasChild(Element who, Element child) {
        if (who.equals(child))
            return true;
        LinkedList list = new LinkedList(((MetadataElement) who).getChildren());
        while (!list.isEmpty()) {
            MetadataElement e = (MetadataElement) list.removeFirst();
            if (e.equals(child))
                return true;
            list.addAll(e.getChildren());
        }
        return false;
    }
    
    private Statement getStatement(Element e) {
        if (e instanceof Feature || e instanceof Resource)
            return null;
        while (!(e instanceof Statement) && e != null)
            e = (Element) e.refImmediateComposite();
        return (Statement) e;
    }
}
... 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.