/* * The contents of this file are subject to the terms of the Common Development * and Distribution License (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at http://www.netbeans.org/cddl.html * or http://www.netbeans.org/cddl.txt. * * When distributing Covered Code, include this CDDL Header Notice in each file * and include the License file at http://www.netbeans.org/cddl.txt. * If applicable, add the following below the CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * The Original Software is NetBeans. The Initial Developer of the Original * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.gwt4nb.services.refactoring.ui; import com.sun.source.util.TreePath; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.swing.event.ChangeListener; import org.netbeans.api.java.source.CompilationInfo; import org.netbeans.api.java.source.TreePathHandle; import org.netbeans.api.java.source.ui.ElementHeaders; import org.netbeans.modules.gwt4nb.services.ServiceClassSet; import org.netbeans.modules.gwt4nb.services.ServiceClassSetUtils; import org.netbeans.modules.refactoring.api.AbstractRefactoring; import org.netbeans.modules.refactoring.api.Problem; import org.netbeans.modules.gwt4nb.services.refactoring.ServiceDeleteRefactoring; import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel; import org.netbeans.modules.refactoring.spi.ui.RefactoringUI; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; /** Refactoring UI object for Service Delete refactoring. * * @author Martin Matula */ public class ServiceDeleteRefactoringUI implements RefactoringUI { // reference to Service Delete refactoring this UI object corresponds to private final ServiceDeleteRefactoring refactoring; // initially selected members private final ServiceClassSet serviceClassSet; // UI panel for collecting parameters private ServiceDeletePanel panel; private String description; /** Creates a new instance of ServiceDeleteRefactoringUI * @param selectedElements Elements the refactoring action was invoked on. */ public ServiceDeleteRefactoringUI(TreePathHandle[] selectedElements, CompilationInfo info) { TypeElement clazz = (TypeElement)info.getTrees().getElement( selectedElements[0].resolve(info)); serviceClassSet = ServiceClassSetUtils.resolveServiceClassSet(info, clazz); // compute source type and members that should be pre-selected from the // set of elements the action was invoked on // create an instance of Service Delete refactoring object Element selected = selectedElements[0].resolveElement(info); if (!(selected instanceof TypeElement)) { selected = info.getElementUtilities().enclosingTypeElement(selected); } TreePath tp = info.getTrees().getPath(selected); TreePathHandle sourceType = TreePathHandle.create(tp, info); description = ElementHeaders.getHeader(tp, info, ElementHeaders.NAME); refactoring = new ServiceDeleteRefactoring(Lookups.singleton(sourceType)); refactoring.getContext().add(info.getClasspathInfo()); } // --- IMPLEMENTATION OF RefactoringUI INTERFACE --------------------------- public boolean isQuery() { return false; } public CustomRefactoringPanel getPanel(ChangeListener parent) { if (panel == null) { panel = new ServiceDeletePanel(refactoring, serviceClassSet, parent); } return panel; } public Problem setParameters() { captureParameters(); return refactoring.checkParameters(); } public Problem checkParameters() { captureParameters(); return refactoring.fastCheckParameters(); } public AbstractRefactoring getRefactoring() { return refactoring; } public String getDescription() { return NbBundle.getMessage(ServiceDeleteAction.class, "DSC_ServiceDelete", description); // NOI18N } public String getName() { return NbBundle.getMessage(ServiceDeleteAction.class, "LBL_ServiceDelete"); // NOI18N } public boolean hasParameters() { return true; } public HelpCtx getHelpCtx() { return new HelpCtx(ServiceDeleteRefactoringUI.class.getName()); } // --- PRIVATE HELPER METHODS ---------------------------------------------- /** Gets parameters from the refactoring panel and sets them * to the refactoring object. */ private void captureParameters() { refactoring.setMembers(serviceClassSet); } // /** Method that computes the source type and initially selected members from // * elements the refactoring action was invoked on. // * It tries to find a common parent class for the elements to return it as the // * the source type. If not all elements // * have a common parent class, then the class that is a parent class for majority // * of the elements is chosen. The parent JavaClass, Field, Method or MultipartId that // * is part of interface names of a class is taken as the pre-selected member. // * @elements The elements the refactoring was invoked on. // * @serviceClassSet Should be an empty set that this method will add the members // * that should be selected. // * @return Source type. // */ // private static JavaClass getSourceType(Element[] elements, Set serviceClassSet) { // JavaClass result = null; // // map that will be used to compute final source type and pre-selected members // // maps suggested source type to a set of its suggested pre-selected members // HashMap elementsByClass = new HashMap(); // // for (int i = 0; i < elements.length; i++) { // Element element = null; // Element temp = elements[i]; // // iterate through the containers of the element (until we get to null // // or a resource) // while (temp != null && !(temp instanceof Resource)) { // if ((temp instanceof JavaClass) || (temp instanceof Field) || (temp instanceof Method)) { // // if the current element is a class, field or a method, exit // // the loop - we have an element that will likely be the member // // to be initially selected // break; // } else if (temp instanceof MultipartId) { // // if the current element is a MultipartId, remember it, but // // go further to find the top-most MultipartId // // if the MultipartId is part of interface names of a class, // // then its direct parent should be JavaClass, so when // // we exit the loop, "element" variable will contain the MultipartId // // and the "temp" variable will contain its parent class. // element = temp; // } // temp = (Element) temp.refImmediateComposite(); // } // // if temp is null, the element is not in a resource -> ignore it // if (temp == null) continue; // // if element is a resource, find the primary class in it // // (the class with the same name as the resource) // if (temp instanceof Resource) { // element = null; // String name = ((Resource) temp).getName(); // int start = name.lastIndexOf('/') + 1; // int end = name.indexOf('.', start); // if (end < 0) end = name.length(); // name = name.substring(start, end); // for (Iterator it = ((Resource) temp).getClassifiers().iterator(); it.hasNext();) { // JavaClass cls = (JavaClass) it.next(); // temp = cls; // // if the class of a same name is found, exit the loop // if (name.equals(cls.getSimpleName())) break; // } // // if no class of the same name is found, then the last class in // // the resource is taken as the selected one // } // if (temp instanceof JavaClass) { // // if the found element is a class, check whether element is not null // // and is part of the interface names in class implements clause // if (element == null || !((JavaClass) temp).getInterfaceNames().contains(element)) { // // if not, add the class as a suggested source type (i.e. in place of a key in the map) // addToMap(elementsByClass, (JavaClass) temp, null); // } else { // // if so, the selected element is the interface name // // put the class into element variable (which will later be added as a key // // - i.e. as the suggested source type - into the map) and // // the interface name into the temp variable (which will later be added // // as a value to the map - i.e. as a suggested pre-selected member) // Element cls = temp; // temp = element; // element = cls; // } // } // if (temp instanceof Feature) { // // if the element found is a feature (i.e. either JavaClass, or Field or a Method) // // store its declaring class in element variable (as a suggested source type) // element = ((Feature) temp).getDeclaringClass(); // } // // if the thing in the element variable (i.e. the suggested source type) // // is of a correct type (i.e. JavaClass) add the type and the member to the // // map that will be used to compute final source type and pre-selected members // if (element instanceof JavaClass) { // addToMap(elementsByClass, (JavaClass) element, temp); // } // } // // // now go through the map and find the suggested source type corresponding // // to the highest number of the pre-selected members // Set maxMembers = Collections.EMPTY_SET; // for (Iterator it = elementsByClass.entrySet().iterator(); it.hasNext();) { // Map.Entry entry = (Map.Entry) it.next(); // Set value = (Set) entry.getValue(); // // if the number of members for this source type // // is higher than the last max., take it as max // // note that even when the number is equal, but the set of members contains // // null, it takes a precedence - this is to correctly handle the case when the // // only selected element is an inner class (the map will contain two records: // // 1 - outer->inner, 2 - inner->null). In this case the algorithm chooses the inner class // // to be the source type with no members pre-selected. // if ((maxMembers.size() < value.size()) || ((maxMembers.size() == value.size()) && value.contains(null))) { // maxMembers = value; // result = (JavaClass) entry.getKey(); // } // } // serviceClassSet.addAll(maxMembers); // // return result; // } // /** Helper method that simplifies adding members to the map of // * suggested source types to the set of members. // * @param map Map to add a new record to. // * @param parentClass Map key - suggested source type. // * @param member A new value for the key - pre-selected member. // */ // private static void addToMap(Map map, JavaClass parentClass, Element member) { // Set value = (Set) map.get(parentClass); // if (value == null) { // value = new HashSet(); // map.put(parentClass, value); // } // value.add(member); // } }