| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.web.refactoring; |
| |
| import java.io.BufferedReader; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.UnsupportedEncodingException; |
| import java.lang.reflect.InvocationTargetException; |
| import javax.swing.JEditorPane; |
| import javax.swing.SwingUtilities; |
| import javax.swing.text.BadLocationException; |
| import org.netbeans.editor.BaseDocument; |
| import org.openide.loaders.DataObject; |
| import org.openide.text.CloneableEditorSupport; |
| import org.openide.text.PositionBounds; |
| import javax.swing.text.Position.Bias; |
| import org.openide.nodes.Node; |
| import org.openide.text.PositionRef; |
| import org.openide.util.Exceptions; |
| import org.openide.util.Parameters; |
| |
| /** |
| * Resolves position bounds of an element that is being refactored. If the |
| * <code>elementName</code> is null or no matching string can be found in the data |
| * object, returns <code>PositionBounds</code> that represents the beginning of the file. |
| * |
| * @author Erno Mononen |
| */ |
| // TODO: Copied from jpa/refactoring. |
| public class PositionBoundsResolver { |
| |
| /** |
| * The data object that is being refactored. |
| */ |
| private final DataObject dataObject; |
| /** |
| * The editor support associated with the data object. |
| */ |
| private final CloneableEditorSupport editorSupport; |
| |
| /** |
| * Name of the element that is being refactored. If the element represents class, |
| * it should be its fully qualified name. |
| */ |
| private final String elementName; |
| |
| /** |
| * Creates a new resolver for the given <code>dataObject</code>. |
| * @param dataObject the data object that is being refactored. Must have an |
| * associated <code>CloneableEditorSupport</code> and must not be null. |
| * @param elementName the element that is being refactored. If the element represents class, |
| * it should be its fully qualified name. If a <code>null</code> is given, {@link #getPositionBounds} |
| * returns PositionBounds that represents the beginning of the file. |
| * @throws IllegalArgumentException if the given <code>dataObject</code> was null |
| * or if didn't have CloneableEditorSupport associated. |
| */ |
| public PositionBoundsResolver(DataObject dataObject, String elementName) { |
| Parameters.notNull("dataObject", dataObject); |
| this.dataObject = dataObject; |
| this.editorSupport = findCloneableEditorSupport(); |
| |
| if (this.editorSupport == null){ |
| throw new IllegalArgumentException("Couldn't get CloneableEditorSupport for " + dataObject); //NO18N |
| } |
| this.elementName = elementName; |
| } |
| |
| /** |
| *@return PositionBounds representing the position of the name of the entity that is being |
| * refactored or PostionBounds representing the start of the file if the position |
| * of the entity could not be resolved. |
| */ |
| public PositionBounds getPositionBounds(){ |
| if (elementName != null){ |
| try { |
| BaseDocument doc = getDocument(); |
| String text = doc.getText(0, doc.getLength()); |
| int offset = text.indexOf(elementName); |
| if (offset > -1){ |
| PositionRef start = editorSupport.createPositionRef(offset, Bias.Forward); |
| PositionRef end = editorSupport.createPositionRef(offset + elementName.length(), Bias.Backward); |
| return new PositionBounds(start, end); |
| } |
| } catch (BadLocationException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| return getDefaultPositionBounds(); |
| } |
| |
| /** |
| * @return PositionBounds representing the beginning of the file associated |
| * with the <code>dataObject</code>. |
| */ |
| private PositionBounds getDefaultPositionBounds(){ |
| PositionRef start = editorSupport.createPositionRef(0, Bias.Forward); |
| PositionRef end = editorSupport.createPositionRef(0, Bias.Backward); |
| return new PositionBounds(start, end); |
| } |
| |
| |
| // adapted from JSFEditorUtilities |
| private CloneableEditorSupport findCloneableEditorSupport() { |
| Node.Cookie obj = dataObject.getCookie(org.openide.cookies.OpenCookie.class); |
| if (obj instanceof CloneableEditorSupport) { |
| return (CloneableEditorSupport)obj; |
| } |
| obj = dataObject.getCookie(org.openide.cookies.EditorCookie.class); |
| if (obj instanceof CloneableEditorSupport) { |
| return (CloneableEditorSupport)obj; |
| } |
| return null; |
| } |
| |
| /** |
| * @return the BaseDocument representing contents of our <code>dataObject</code>. |
| */ |
| private BaseDocument getDocument(){ |
| BaseDocument result = (BaseDocument) editorSupport.getDocument(); |
| // editor was not opened |
| if (result == null) { |
| final CreateXMLPane runnable = new CreateXMLPane(); |
| try { |
| if (SwingUtilities.isEventDispatchThread()){ |
| runnable.run(); |
| } else { |
| SwingUtilities.invokeAndWait(runnable); |
| } |
| result = new BaseDocument(runnable.getPane().getEditorKit().getClass(), false); |
| String text= readResource(dataObject.getPrimaryFile().getInputStream()); |
| result.remove(0, result.getLength()); |
| result.insertString(0, text, null); |
| } catch (InterruptedException ex) { |
| Exceptions.printStackTrace(ex); |
| } catch (InvocationTargetException ex) { |
| Exceptions.printStackTrace(ex); |
| } catch (FileNotFoundException ex) { |
| Exceptions.printStackTrace(ex); |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } catch (BadLocationException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| return result; |
| |
| } |
| |
| /** |
| * Reads the given stream. |
| */ |
| private String readResource(InputStream stream){ |
| StringBuffer result = new StringBuffer(); |
| String lineSep = System.getProperty("line.separator");//NO18N |
| BufferedReader reader = null; |
| try { |
| reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));//NO18N |
| String line = reader.readLine(); |
| while (line != null) { |
| result.append(line); |
| result.append(lineSep); |
| line = reader.readLine(); |
| } |
| } catch (UnsupportedEncodingException ex) { |
| Exceptions.printStackTrace(ex); |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } finally { |
| try { |
| if (reader != null){ |
| reader.close(); |
| } |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| return result.toString(); |
| } |
| |
| // copied from JSFFrameworkProvider |
| private static class CreateXMLPane implements Runnable{ |
| JEditorPane pane; |
| |
| public void run(){ |
| pane = new JEditorPane("text/xml", ""); |
| } |
| |
| public JEditorPane getPane(){ |
| return pane; |
| } |
| } |
| |
| } |