aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java1403
1 files changed, 0 insertions, 1403 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java
deleted file mode 100644
index 904a3a084..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
-
-import static com.android.SdkConstants.ANDROID_NS_NAME;
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.ANDROID_WIDGET_PREFIX;
-import static com.android.SdkConstants.ATTR_ID;
-import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
-import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX;
-import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
-import static com.android.SdkConstants.ID_PREFIX;
-import static com.android.SdkConstants.NEW_ID_PREFIX;
-import static com.android.SdkConstants.XMLNS;
-import static com.android.SdkConstants.XMLNS_PREFIX;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.VisibleForTesting;
-import com.android.ide.common.xml.XmlFormatStyle;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlFormatPreferences;
-import com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlPrettyPrinter;
-import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationDescription;
-import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
-import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
-import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
-import com.android.utils.Pair;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.ITextSelection;
-import org.eclipse.jface.viewers.ITreeSelection;
-import org.eclipse.jface.viewers.TreePath;
-import org.eclipse.ltk.core.refactoring.Change;
-import org.eclipse.ltk.core.refactoring.ChangeDescriptor;
-import org.eclipse.ltk.core.refactoring.CompositeChange;
-import org.eclipse.ltk.core.refactoring.Refactoring;
-import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
-import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
-import org.eclipse.ltk.core.refactoring.RefactoringStatus;
-import org.eclipse.text.edits.DeleteEdit;
-import org.eclipse.text.edits.InsertEdit;
-import org.eclipse.text.edits.MalformedTreeException;
-import org.eclipse.text.edits.MultiTextEdit;
-import org.eclipse.text.edits.ReplaceEdit;
-import org.eclipse.text.edits.TextEdit;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.ide.IDE;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
-import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Parent class for the various visual refactoring operations; contains shared
- * implementations needed by most of them
- */
-@SuppressWarnings("restriction") // XML model
-public abstract class VisualRefactoring extends Refactoring {
- private static final String KEY_FILE = "file"; //$NON-NLS-1$
- private static final String KEY_PROJECT = "proj"; //$NON-NLS-1$
- private static final String KEY_SEL_START = "sel-start"; //$NON-NLS-1$
- private static final String KEY_SEL_END = "sel-end"; //$NON-NLS-1$
-
- protected final IFile mFile;
- protected final LayoutEditorDelegate mDelegate;
- protected final IProject mProject;
- protected int mSelectionStart = -1;
- protected int mSelectionEnd = -1;
- protected final List<Element> mElements;
- protected final ITreeSelection mTreeSelection;
- protected final ITextSelection mSelection;
- /** Same as {@link #mSelectionStart} but not adjusted to element edges */
- protected int mOriginalSelectionStart = -1;
- /** Same as {@link #mSelectionEnd} but not adjusted to element edges */
- protected int mOriginalSelectionEnd = -1;
-
- protected final Map<Element, String> mGeneratedIdMap = new HashMap<Element, String>();
- protected final Set<String> mGeneratedIds = new HashSet<String>();
-
- protected List<Change> mChanges;
- private String mAndroidNamespacePrefix;
-
- /**
- * This constructor is solely used by {@link VisualRefactoringDescriptor},
- * to replay a previous refactoring.
- * @param arguments argument map created by #createArgumentMap.
- */
- VisualRefactoring(Map<String, String> arguments) {
- IPath path = Path.fromPortableString(arguments.get(KEY_PROJECT));
- mProject = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(path);
- path = Path.fromPortableString(arguments.get(KEY_FILE));
- mFile = (IFile) ResourcesPlugin.getWorkspace().getRoot().findMember(path);
- mSelectionStart = Integer.parseInt(arguments.get(KEY_SEL_START));
- mSelectionEnd = Integer.parseInt(arguments.get(KEY_SEL_END));
- mOriginalSelectionStart = mSelectionStart;
- mOriginalSelectionEnd = mSelectionEnd;
- mDelegate = null;
- mElements = null;
- mSelection = null;
- mTreeSelection = null;
- }
-
- @VisibleForTesting
- VisualRefactoring(List<Element> elements, LayoutEditorDelegate delegate) {
- mElements = elements;
- mDelegate = delegate;
-
- mFile = delegate != null ? delegate.getEditor().getInputFile() : null;
- mProject = delegate != null ? delegate.getEditor().getProject() : null;
- mSelectionStart = 0;
- mSelectionEnd = 0;
- mOriginalSelectionStart = 0;
- mOriginalSelectionEnd = 0;
- mSelection = null;
- mTreeSelection = null;
-
- int end = Integer.MIN_VALUE;
- int start = Integer.MAX_VALUE;
- for (Element element : elements) {
- if (element instanceof IndexedRegion) {
- IndexedRegion region = (IndexedRegion) element;
- start = Math.min(start, region.getStartOffset());
- end = Math.max(end, region.getEndOffset());
- }
- }
- if (start >= 0) {
- mSelectionStart = start;
- mSelectionEnd = end;
- mOriginalSelectionStart = start;
- mOriginalSelectionEnd = end;
- }
- }
-
- public VisualRefactoring(IFile file, LayoutEditorDelegate editor, ITextSelection selection,
- ITreeSelection treeSelection) {
- mFile = file;
- mDelegate = editor;
- mProject = file.getProject();
- mSelection = selection;
- mTreeSelection = treeSelection;
-
- // Initialize mSelectionStart and mSelectionEnd based on the selection context, which
- // is either a treeSelection (when invoked from the layout editor or the outline), or
- // a selection (when invoked from an XML editor)
- if (treeSelection != null) {
- int end = Integer.MIN_VALUE;
- int start = Integer.MAX_VALUE;
- for (TreePath path : treeSelection.getPaths()) {
- Object lastSegment = path.getLastSegment();
- if (lastSegment instanceof CanvasViewInfo) {
- CanvasViewInfo viewInfo = (CanvasViewInfo) lastSegment;
- UiViewElementNode uiNode = viewInfo.getUiViewNode();
- if (uiNode == null) {
- continue;
- }
- Node xmlNode = uiNode.getXmlNode();
- if (xmlNode instanceof IndexedRegion) {
- IndexedRegion region = (IndexedRegion) xmlNode;
-
- start = Math.min(start, region.getStartOffset());
- end = Math.max(end, region.getEndOffset());
- }
- }
- }
- if (start >= 0) {
- mSelectionStart = start;
- mSelectionEnd = end;
- mOriginalSelectionStart = mSelectionStart;
- mOriginalSelectionEnd = mSelectionEnd;
- }
- if (selection != null) {
- mOriginalSelectionStart = selection.getOffset();
- mOriginalSelectionEnd = mOriginalSelectionStart + selection.getLength();
- }
- } else if (selection != null) {
- // TODO: update selection to boundaries!
- mSelectionStart = selection.getOffset();
- mSelectionEnd = mSelectionStart + selection.getLength();
- mOriginalSelectionStart = mSelectionStart;
- mOriginalSelectionEnd = mSelectionEnd;
- }
-
- mElements = initElements();
- }
-
- @NonNull
- protected abstract List<Change> computeChanges(IProgressMonitor monitor);
-
- @Override
- public RefactoringStatus checkFinalConditions(IProgressMonitor monitor) throws CoreException,
- OperationCanceledException {
- RefactoringStatus status = new RefactoringStatus();
- mChanges = new ArrayList<Change>();
- try {
- monitor.beginTask("Checking post-conditions...", 5);
-
- // Reset state for each computeChanges call, in case the user goes back
- // and forth in the refactoring wizard
- mGeneratedIdMap.clear();
- mGeneratedIds.clear();
- List<Change> changes = computeChanges(monitor);
- mChanges.addAll(changes);
-
- monitor.worked(1);
- } finally {
- monitor.done();
- }
-
- return status;
- }
-
- @Override
- public Change createChange(IProgressMonitor monitor) throws CoreException,
- OperationCanceledException {
- try {
- monitor.beginTask("Applying changes...", 1);
-
- CompositeChange change = new CompositeChange(
- getName(),
- mChanges.toArray(new Change[mChanges.size()])) {
- @Override
- public ChangeDescriptor getDescriptor() {
- VisualRefactoringDescriptor desc = createDescriptor();
- return new RefactoringChangeDescriptor(desc);
- }
- };
-
- monitor.worked(1);
- return change;
-
- } finally {
- monitor.done();
- }
- }
-
- protected abstract VisualRefactoringDescriptor createDescriptor();
-
- protected Map<String, String> createArgumentMap() {
- HashMap<String, String> args = new HashMap<String, String>();
- args.put(KEY_PROJECT, mProject.getFullPath().toPortableString());
- args.put(KEY_FILE, mFile.getFullPath().toPortableString());
- args.put(KEY_SEL_START, Integer.toString(mSelectionStart));
- args.put(KEY_SEL_END, Integer.toString(mSelectionEnd));
-
- return args;
- }
-
- IFile getFile() {
- return mFile;
- }
-
- // ---- Shared functionality ----
-
-
- protected void openFile(IFile file) {
- GraphicalEditorPart graphicalEditor = mDelegate.getGraphicalEditor();
- IFile leavingFile = graphicalEditor.getEditedFile();
-
- try {
- // Duplicate the current state into the newly created file
- String state = ConfigurationDescription.getDescription(leavingFile);
-
- // TODO: Look for a ".NoTitleBar.Fullscreen" theme version of the current
- // theme to show.
-
- file.setSessionProperty(GraphicalEditorPart.NAME_INITIAL_STATE, state);
- } catch (CoreException e) {
- // pass
- }
-
- /* TBD: "Show Included In" if supported.
- * Not sure if this is a good idea.
- if (graphicalEditor.renderingSupports(Capability.EMBEDDED_LAYOUT)) {
- try {
- Reference include = Reference.create(graphicalEditor.getEditedFile());
- file.setSessionProperty(GraphicalEditorPart.NAME_INCLUDE, include);
- } catch (CoreException e) {
- // pass - worst that can happen is that we don't start with inclusion
- }
- }
- */
-
- try {
- IEditorPart part =
- IDE.openEditor(mDelegate.getEditor().getEditorSite().getPage(), file);
- if (part instanceof AndroidXmlEditor && AdtPrefs.getPrefs().getFormatGuiXml()) {
- AndroidXmlEditor newEditor = (AndroidXmlEditor) part;
- newEditor.reformatDocument();
- }
- } catch (PartInitException e) {
- AdtPlugin.log(e, "Can't open new included layout");
- }
- }
-
-
- /** Produce a list of edits to replace references to the given id with the given new id */
- protected static List<TextEdit> replaceIds(String androidNamePrefix,
- IStructuredDocument doc, int skipStart, int skipEnd,
- String rootId, String referenceId) {
- if (rootId == null) {
- return Collections.emptyList();
- }
-
- // We need to search for either @+id/ or @id/
- String match1 = rootId;
- String match2;
- if (match1.startsWith(ID_PREFIX)) {
- match2 = '"' + NEW_ID_PREFIX + match1.substring(ID_PREFIX.length()) + '"';
- match1 = '"' + match1 + '"';
- } else if (match1.startsWith(NEW_ID_PREFIX)) {
- match2 = '"' + ID_PREFIX + match1.substring(NEW_ID_PREFIX.length()) + '"';
- match1 = '"' + match1 + '"';
- } else {
- return Collections.emptyList();
- }
-
- String namePrefix = androidNamePrefix + ':' + ATTR_LAYOUT_RESOURCE_PREFIX;
- List<TextEdit> edits = new ArrayList<TextEdit>();
-
- IStructuredDocumentRegion region = doc.getFirstStructuredDocumentRegion();
- for (; region != null; region = region.getNext()) {
- ITextRegionList list = region.getRegions();
- int regionStart = region.getStart();
-
- // Look at all attribute values and look for an id reference match
- String attributeName = ""; //$NON-NLS-1$
- for (int j = 0; j < region.getNumberOfRegions(); j++) {
- ITextRegion subRegion = list.get(j);
- String type = subRegion.getType();
- if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(type)) {
- attributeName = region.getText(subRegion);
- } else if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(type)) {
- // Only replace references in layout attributes
- if (!attributeName.startsWith(namePrefix)) {
- continue;
- }
- // Skip occurrences in the given skip range
- int subRegionStart = regionStart + subRegion.getStart();
- if (subRegionStart >= skipStart && subRegionStart <= skipEnd) {
- continue;
- }
-
- String attributeValue = region.getText(subRegion);
- if (attributeValue.equals(match1) || attributeValue.equals(match2)) {
- int start = subRegionStart + 1; // skip quote
- int end = start + rootId.length();
-
- edits.add(new ReplaceEdit(start, end - start, referenceId));
- }
- }
- }
- }
-
- return edits;
- }
-
- /** Get the id of the root selected element, if any */
- protected String getRootId() {
- Element primary = getPrimaryElement();
- if (primary != null) {
- String oldId = primary.getAttributeNS(ANDROID_URI, ATTR_ID);
- // id null check for https://bugs.eclipse.org/bugs/show_bug.cgi?id=272378
- if (oldId != null && oldId.length() > 0) {
- return oldId;
- }
- }
-
- return null;
- }
-
- protected String getAndroidNamespacePrefix() {
- if (mAndroidNamespacePrefix == null) {
- List<Attr> attributeNodes = findNamespaceAttributes();
- for (Node attributeNode : attributeNodes) {
- String prefix = attributeNode.getPrefix();
- if (XMLNS.equals(prefix)) {
- String name = attributeNode.getNodeName();
- String value = attributeNode.getNodeValue();
- if (value.equals(ANDROID_URI)) {
- mAndroidNamespacePrefix = name;
- if (mAndroidNamespacePrefix.startsWith(XMLNS_PREFIX)) {
- mAndroidNamespacePrefix =
- mAndroidNamespacePrefix.substring(XMLNS_PREFIX.length());
- }
- }
- }
- }
-
- if (mAndroidNamespacePrefix == null) {
- mAndroidNamespacePrefix = ANDROID_NS_NAME;
- }
- }
-
- return mAndroidNamespacePrefix;
- }
-
- protected static String getAndroidNamespacePrefix(Document document) {
- String nsPrefix = null;
- List<Attr> attributeNodes = findNamespaceAttributes(document);
- for (Node attributeNode : attributeNodes) {
- String prefix = attributeNode.getPrefix();
- if (XMLNS.equals(prefix)) {
- String name = attributeNode.getNodeName();
- String value = attributeNode.getNodeValue();
- if (value.equals(ANDROID_URI)) {
- nsPrefix = name;
- if (nsPrefix.startsWith(XMLNS_PREFIX)) {
- nsPrefix =
- nsPrefix.substring(XMLNS_PREFIX.length());
- }
- }
- }
- }
-
- if (nsPrefix == null) {
- nsPrefix = ANDROID_NS_NAME;
- }
-
- return nsPrefix;
- }
-
- protected List<Attr> findNamespaceAttributes() {
- Document document = getDomDocument();
- return findNamespaceAttributes(document);
- }
-
- protected static List<Attr> findNamespaceAttributes(Document document) {
- if (document != null) {
- Element root = document.getDocumentElement();
- return findNamespaceAttributes(root);
- }
-
- return Collections.emptyList();
- }
-
- protected static List<Attr> findNamespaceAttributes(Node root) {
- List<Attr> result = new ArrayList<Attr>();
- NamedNodeMap attributes = root.getAttributes();
- for (int i = 0, n = attributes.getLength(); i < n; i++) {
- Node attributeNode = attributes.item(i);
-
- String prefix = attributeNode.getPrefix();
- if (XMLNS.equals(prefix)) {
- result.add((Attr) attributeNode);
- }
- }
-
- return result;
- }
-
- protected List<Attr> findLayoutAttributes(Node root) {
- List<Attr> result = new ArrayList<Attr>();
- NamedNodeMap attributes = root.getAttributes();
- for (int i = 0, n = attributes.getLength(); i < n; i++) {
- Node attributeNode = attributes.item(i);
-
- String name = attributeNode.getLocalName();
- if (name.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)
- && ANDROID_URI.equals(attributeNode.getNamespaceURI())) {
- result.add((Attr) attributeNode);
- }
- }
-
- return result;
- }
-
- protected String insertNamespace(String xmlText, String namespaceDeclarations) {
- // Insert namespace declarations into the extracted XML fragment
- int firstSpace = xmlText.indexOf(' ');
- int elementEnd = xmlText.indexOf('>');
- int insertAt;
- if (firstSpace != -1 && firstSpace < elementEnd) {
- insertAt = firstSpace;
- } else {
- insertAt = elementEnd;
- }
- xmlText = xmlText.substring(0, insertAt) + namespaceDeclarations
- + xmlText.substring(insertAt);
-
- return xmlText;
- }
-
- /** Remove sections of the document that correspond to top level layout attributes;
- * these are placed on the include element instead */
- protected String stripTopLayoutAttributes(Element primary, int start, String xml) {
- if (primary != null) {
- // List of attributes to remove
- List<IndexedRegion> skip = new ArrayList<IndexedRegion>();
- NamedNodeMap attributes = primary.getAttributes();
- for (int i = 0, n = attributes.getLength(); i < n; i++) {
- Node attr = attributes.item(i);
- String name = attr.getLocalName();
- if (name.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)
- && ANDROID_URI.equals(attr.getNamespaceURI())) {
- if (name.equals(ATTR_LAYOUT_WIDTH) || name.equals(ATTR_LAYOUT_HEIGHT)) {
- // These are special and are left in
- continue;
- }
-
- if (attr instanceof IndexedRegion) {
- skip.add((IndexedRegion) attr);
- }
- }
- }
- if (skip.size() > 0) {
- Collections.sort(skip, new Comparator<IndexedRegion>() {
- // Sort in start order
- @Override
- public int compare(IndexedRegion r1, IndexedRegion r2) {
- return r1.getStartOffset() - r2.getStartOffset();
- }
- });
-
- // Successively cut out the various layout attributes
- // TODO remove adjacent whitespace too (but not newlines, unless they
- // are newly adjacent)
- StringBuilder sb = new StringBuilder(xml.length());
- int nextStart = 0;
-
- // Copy out all the sections except the skip sections
- for (IndexedRegion r : skip) {
- int regionStart = r.getStartOffset();
- // Adjust to string offsets since we've copied the string out of
- // the document
- regionStart -= start;
-
- sb.append(xml.substring(nextStart, regionStart));
-
- nextStart = regionStart + r.getLength();
- }
- if (nextStart < xml.length()) {
- sb.append(xml.substring(nextStart));
- }
-
- return sb.toString();
- }
- }
-
- return xml;
- }
-
- protected static String getIndent(String line, int max) {
- int i = 0;
- int n = Math.min(max, line.length());
- for (; i < n; i++) {
- char c = line.charAt(i);
- if (!Character.isWhitespace(c)) {
- return line.substring(0, i);
- }
- }
-
- if (n < line.length()) {
- return line.substring(0, n);
- } else {
- return line;
- }
- }
-
- protected static String dedent(String xml) {
- String[] lines = xml.split("\n"); //$NON-NLS-1$
- if (lines.length < 2) {
- // The first line never has any indentation since we copy it out from the
- // element start index
- return xml;
- }
-
- String indentPrefix = getIndent(lines[1], lines[1].length());
- for (int i = 2, n = lines.length; i < n; i++) {
- String line = lines[i];
-
- // Ignore blank lines
- if (line.trim().length() == 0) {
- continue;
- }
-
- indentPrefix = getIndent(line, indentPrefix.length());
-
- if (indentPrefix.length() == 0) {
- return xml;
- }
- }
-
- StringBuilder sb = new StringBuilder();
- for (String line : lines) {
- if (line.startsWith(indentPrefix)) {
- sb.append(line.substring(indentPrefix.length()));
- } else {
- sb.append(line);
- }
- sb.append('\n');
- }
- return sb.toString();
- }
-
- protected String getText(int start, int end) {
- try {
- IStructuredDocument document = mDelegate.getEditor().getStructuredDocument();
- return document.get(start, end - start);
- } catch (BadLocationException e) {
- // the region offset was invalid. ignore.
- return null;
- }
- }
-
- protected List<Element> getElements() {
- return mElements;
- }
-
- protected List<Element> initElements() {
- List<Element> nodes = new ArrayList<Element>();
-
- assert mTreeSelection == null || mSelection == null :
- "treeSel= " + mTreeSelection + ", sel=" + mSelection;
-
- // Initialize mSelectionStart and mSelectionEnd based on the selection context, which
- // is either a treeSelection (when invoked from the layout editor or the outline), or
- // a selection (when invoked from an XML editor)
- if (mTreeSelection != null) {
- int end = Integer.MIN_VALUE;
- int start = Integer.MAX_VALUE;
- for (TreePath path : mTreeSelection.getPaths()) {
- Object lastSegment = path.getLastSegment();
- if (lastSegment instanceof CanvasViewInfo) {
- CanvasViewInfo viewInfo = (CanvasViewInfo) lastSegment;
- UiViewElementNode uiNode = viewInfo.getUiViewNode();
- if (uiNode == null) {
- continue;
- }
- Node xmlNode = uiNode.getXmlNode();
- if (xmlNode instanceof Element) {
- Element element = (Element) xmlNode;
- nodes.add(element);
- IndexedRegion region = getRegion(element);
- start = Math.min(start, region.getStartOffset());
- end = Math.max(end, region.getEndOffset());
- }
- }
- }
- if (start >= 0) {
- mSelectionStart = start;
- mSelectionEnd = end;
- }
- } else if (mSelection != null) {
- mSelectionStart = mSelection.getOffset();
- mSelectionEnd = mSelectionStart + mSelection.getLength();
- mOriginalSelectionStart = mSelectionStart;
- mOriginalSelectionEnd = mSelectionEnd;
-
- // Figure out the range of selected nodes from the document offsets
- IStructuredDocument doc = mDelegate.getEditor().getStructuredDocument();
- Pair<Element, Element> range = DomUtilities.getElementRange(doc,
- mSelectionStart, mSelectionEnd);
- if (range != null) {
- Element first = range.getFirst();
- Element last = range.getSecond();
-
- // Adjust offsets to get rid of surrounding text nodes (if you happened
- // to select a text range and included whitespace on either end etc)
- mSelectionStart = getRegion(first).getStartOffset();
- mSelectionEnd = getRegion(last).getEndOffset();
-
- if (mSelectionStart > mSelectionEnd) {
- int tmp = mSelectionStart;
- mSelectionStart = mSelectionEnd;
- mSelectionEnd = tmp;
- }
-
- if (first == last) {
- nodes.add(first);
- } else if (first.getParentNode() == last.getParentNode()) {
- // Add the range
- Node node = first;
- while (node != null) {
- if (node instanceof Element) {
- nodes.add((Element) node);
- }
- if (node == last) {
- break;
- }
- node = node.getNextSibling();
- }
- } else {
- // Different parents: this means we have an uneven selection, selecting
- // elements from different levels. We can't extract ranges like that.
- }
- }
- } else {
- assert false;
- }
-
- // Make sure that the list of elements is unique
- //Set<Element> seen = new HashSet<Element>();
- //for (Element element : nodes) {
- // assert !seen.contains(element) : element;
- // seen.add(element);
- //}
-
- return nodes;
- }
-
- protected Element getPrimaryElement() {
- List<Element> elements = getElements();
- if (elements != null && elements.size() == 1) {
- return elements.get(0);
- }
-
- return null;
- }
-
- protected Document getDomDocument() {
- if (mDelegate.getUiRootNode() != null) {
- return mDelegate.getUiRootNode().getXmlDocument();
- } else {
- return getElements().get(0).getOwnerDocument();
- }
- }
-
- protected List<CanvasViewInfo> getSelectedViewInfos() {
- List<CanvasViewInfo> infos = new ArrayList<CanvasViewInfo>();
- if (mTreeSelection != null) {
- for (TreePath path : mTreeSelection.getPaths()) {
- Object lastSegment = path.getLastSegment();
- if (lastSegment instanceof CanvasViewInfo) {
- infos.add((CanvasViewInfo) lastSegment);
- }
- }
- }
- return infos;
- }
-
- protected boolean validateNotEmpty(List<CanvasViewInfo> infos, RefactoringStatus status) {
- if (infos.size() == 0) {
- status.addFatalError("No selection to extract");
- return false;
- }
-
- return true;
- }
-
- protected boolean validateNotRoot(List<CanvasViewInfo> infos, RefactoringStatus status) {
- for (CanvasViewInfo info : infos) {
- if (info.isRoot()) {
- status.addFatalError("Cannot refactor the root");
- return false;
- }
- }
-
- return true;
- }
-
- protected boolean validateContiguous(List<CanvasViewInfo> infos, RefactoringStatus status) {
- if (infos.size() > 1) {
- // All elements must be siblings (e.g. same parent)
- List<UiViewElementNode> nodes = new ArrayList<UiViewElementNode>(infos
- .size());
- for (CanvasViewInfo info : infos) {
- UiViewElementNode node = info.getUiViewNode();
- if (node != null) {
- nodes.add(node);
- }
- }
- if (nodes.size() == 0) {
- status.addFatalError("No selected views");
- return false;
- }
-
- UiElementNode parent = nodes.get(0).getUiParent();
- for (UiViewElementNode node : nodes) {
- if (parent != node.getUiParent()) {
- status.addFatalError("The selected elements must be adjacent");
- return false;
- }
- }
- // Ensure that the siblings are contiguous; no gaps.
- // If we've selected all the children of the parent then we don't need
- // to look.
- List<UiElementNode> siblings = parent.getUiChildren();
- if (siblings.size() != nodes.size()) {
- Set<UiViewElementNode> nodeSet = new HashSet<UiViewElementNode>(nodes);
- boolean inRange = false;
- int remaining = nodes.size();
- for (UiElementNode node : siblings) {
- boolean in = nodeSet.contains(node);
- if (in) {
- remaining--;
- if (remaining == 0) {
- break;
- }
- inRange = true;
- } else if (inRange) {
- status.addFatalError("The selected elements must be adjacent");
- return false;
- }
- }
- }
- }
-
- return true;
- }
-
- /**
- * Updates the given element with a new name if the current id reflects the old
- * element type. If the name was changed, it will return the new name.
- */
- protected String ensureIdMatchesType(Element element, String newType, MultiTextEdit rootEdit) {
- String oldType = element.getTagName();
- if (oldType.indexOf('.') == -1) {
- oldType = ANDROID_WIDGET_PREFIX + oldType;
- }
- String oldTypeBase = oldType.substring(oldType.lastIndexOf('.') + 1);
- String id = getId(element);
- if (id == null || id.length() == 0
- || id.toLowerCase(Locale.US).contains(oldTypeBase.toLowerCase(Locale.US))) {
- String newTypeBase = newType.substring(newType.lastIndexOf('.') + 1);
- return ensureHasId(rootEdit, element, newTypeBase);
- }
-
- return null;
- }
-
- /**
- * Returns the {@link IndexedRegion} for the given node
- *
- * @param node the node to look up the region for
- * @return the corresponding region, or null
- */
- public static IndexedRegion getRegion(Node node) {
- if (node instanceof IndexedRegion) {
- return (IndexedRegion) node;
- }
-
- return null;
- }
-
- protected String ensureHasId(MultiTextEdit rootEdit, Element element, String prefix) {
- return ensureHasId(rootEdit, element, prefix, true);
- }
-
- protected String ensureHasId(MultiTextEdit rootEdit, Element element, String prefix,
- boolean apply) {
- String id = mGeneratedIdMap.get(element);
- if (id != null) {
- return NEW_ID_PREFIX + id;
- }
-
- if (!element.hasAttributeNS(ANDROID_URI, ATTR_ID)
- || (prefix != null && !getId(element).startsWith(prefix))) {
- id = DomUtilities.getFreeWidgetId(element, mGeneratedIds, prefix);
- // Make sure we don't use this one again
- mGeneratedIds.add(id);
- mGeneratedIdMap.put(element, id);
- id = NEW_ID_PREFIX + id;
- if (apply) {
- setAttribute(rootEdit, element,
- ANDROID_URI, getAndroidNamespacePrefix(), ATTR_ID, id);
- }
- return id;
- }
-
- return getId(element);
- }
-
- protected int getFirstAttributeOffset(Element element) {
- IndexedRegion region = getRegion(element);
- if (region != null) {
- int startOffset = region.getStartOffset();
- int endOffset = region.getEndOffset();
- String text = getText(startOffset, endOffset);
- String name = element.getLocalName();
- int nameOffset = text.indexOf(name);
- if (nameOffset != -1) {
- return startOffset + nameOffset + name.length();
- }
- }
-
- return -1;
- }
-
- /**
- * Returns the id of the given element
- *
- * @param element the element to look up the id for
- * @return the corresponding id, or an empty string (should not be null
- * according to the DOM API, but has been observed to be null on
- * some versions of Eclipse)
- */
- public static String getId(Element element) {
- return element.getAttributeNS(ANDROID_URI, ATTR_ID);
- }
-
- protected String ensureNewId(String id) {
- if (id != null && id.length() > 0) {
- if (id.startsWith(ID_PREFIX)) {
- id = NEW_ID_PREFIX + id.substring(ID_PREFIX.length());
- } else if (!id.startsWith(NEW_ID_PREFIX)) {
- id = NEW_ID_PREFIX + id;
- }
- } else {
- id = null;
- }
-
- return id;
- }
-
- protected String getViewClass(String fqcn) {
- // Don't include android.widget. as a package prefix in layout files
- if (fqcn.startsWith(ANDROID_WIDGET_PREFIX)) {
- fqcn = fqcn.substring(ANDROID_WIDGET_PREFIX.length());
- }
-
- return fqcn;
- }
-
- protected void setAttribute(MultiTextEdit rootEdit, Element element,
- String attributeUri,
- String attributePrefix, String attributeName, String attributeValue) {
- int offset = getFirstAttributeOffset(element);
- if (offset != -1) {
- if (element.hasAttributeNS(attributeUri, attributeName)) {
- replaceAttributeDeclaration(rootEdit, offset, element, attributePrefix,
- attributeUri, attributeName, attributeValue);
- } else {
- addAttributeDeclaration(rootEdit, offset, attributePrefix, attributeName,
- attributeValue);
- }
- }
- }
-
- private void addAttributeDeclaration(MultiTextEdit rootEdit, int offset,
- String attributePrefix, String attributeName, String attributeValue) {
- StringBuilder sb = new StringBuilder();
- sb.append(' ');
-
- if (attributePrefix != null) {
- sb.append(attributePrefix).append(':');
- }
- sb.append(attributeName).append('=').append('"');
- sb.append(attributeValue).append('"');
-
- InsertEdit setAttribute = new InsertEdit(offset, sb.toString());
- rootEdit.addChild(setAttribute);
- }
-
- /** Replaces the value declaration of the given attribute */
- private void replaceAttributeDeclaration(MultiTextEdit rootEdit, int offset,
- Element element, String attributePrefix, String attributeUri,
- String attributeName, String attributeValue) {
- // Find attribute value and replace it
- IStructuredModel model = mDelegate.getEditor().getModelForRead();
- try {
- IStructuredDocument doc = model.getStructuredDocument();
-
- IStructuredDocumentRegion region = doc.getRegionAtCharacterOffset(offset);
- ITextRegionList list = region.getRegions();
- int regionStart = region.getStart();
-
- int valueStart = -1;
- boolean useNextValue = false;
- String targetName = attributePrefix != null
- ? attributePrefix + ':' + attributeName : attributeName;
-
- // Look at all attribute values and look for an id reference match
- for (int j = 0; j < region.getNumberOfRegions(); j++) {
- ITextRegion subRegion = list.get(j);
- String type = subRegion.getType();
- if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(type)) {
- // What about prefix?
- if (targetName.equals(region.getText(subRegion))) {
- useNextValue = true;
- }
- } else if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(type)) {
- if (useNextValue) {
- valueStart = regionStart + subRegion.getStart();
- break;
- }
- }
- }
-
- if (valueStart != -1) {
- String oldValue = element.getAttributeNS(attributeUri, attributeName);
- int start = valueStart + 1; // Skip opening "
- ReplaceEdit setAttribute = new ReplaceEdit(start, oldValue.length(),
- attributeValue);
- try {
- rootEdit.addChild(setAttribute);
- } catch (MalformedTreeException mte) {
- AdtPlugin.log(mte, "Could not replace attribute %1$s with %2$s",
- attributeName, attributeValue);
- throw mte;
- }
- }
- } finally {
- model.releaseFromRead();
- }
- }
-
- /** Strips out the given attribute, if defined */
- protected void removeAttribute(MultiTextEdit rootEdit, Element element, String uri,
- String attributeName) {
- if (element.hasAttributeNS(uri, attributeName)) {
- Attr attribute = element.getAttributeNodeNS(uri, attributeName);
- removeAttribute(rootEdit, attribute);
- }
- }
-
- /** Strips out the given attribute, if defined */
- protected void removeAttribute(MultiTextEdit rootEdit, Attr attribute) {
- IndexedRegion region = getRegion(attribute);
- if (region != null) {
- int startOffset = region.getStartOffset();
- int endOffset = region.getEndOffset();
- DeleteEdit deletion = new DeleteEdit(startOffset, endOffset - startOffset);
- rootEdit.addChild(deletion);
- }
- }
-
-
- /**
- * Removes the given element's opening and closing tags (including all of its
- * attributes) but leaves any children alone
- *
- * @param rootEdit the multi edit to add the removal operation to
- * @param element the element to delete the open and closing tags for
- * @param skip a list of elements that should not be modified (for example because they
- * are targeted for deletion)
- *
- * TODO: Rename this to "unwrap" ? And allow for handling nested deletions.
- */
- protected void removeElementTags(MultiTextEdit rootEdit, Element element, List<Element> skip,
- boolean changeIndentation) {
- IndexedRegion elementRegion = getRegion(element);
- if (elementRegion == null) {
- return;
- }
-
- // Look for the opening tag
- IStructuredModel model = mDelegate.getEditor().getModelForRead();
- try {
- int startLineInclusive = -1;
- int endLineInclusive = -1;
- IStructuredDocument doc = model.getStructuredDocument();
- if (doc != null) {
- int start = elementRegion.getStartOffset();
- IStructuredDocumentRegion region = doc.getRegionAtCharacterOffset(start);
- ITextRegionList list = region.getRegions();
- int regionStart = region.getStart();
- int startOffset = regionStart;
- for (int j = 0; j < region.getNumberOfRegions(); j++) {
- ITextRegion subRegion = list.get(j);
- String type = subRegion.getType();
- if (DOMRegionContext.XML_TAG_OPEN.equals(type)) {
- startOffset = regionStart + subRegion.getStart();
- } else if (DOMRegionContext.XML_TAG_CLOSE.equals(type)) {
- int endOffset = regionStart + subRegion.getStart() + subRegion.getLength();
-
- DeleteEdit deletion = createDeletion(doc, startOffset, endOffset);
- rootEdit.addChild(deletion);
- startLineInclusive = doc.getLineOfOffset(endOffset) + 1;
- break;
- }
- }
-
- // Find the close tag
- // Look at all attribute values and look for an id reference match
- region = doc.getRegionAtCharacterOffset(elementRegion.getEndOffset()
- - element.getTagName().length() - 1);
- list = region.getRegions();
- regionStart = region.getStartOffset();
- startOffset = -1;
- for (int j = 0; j < region.getNumberOfRegions(); j++) {
- ITextRegion subRegion = list.get(j);
- String type = subRegion.getType();
- if (DOMRegionContext.XML_END_TAG_OPEN.equals(type)) {
- startOffset = regionStart + subRegion.getStart();
- } else if (DOMRegionContext.XML_TAG_CLOSE.equals(type)) {
- int endOffset = regionStart + subRegion.getStart() + subRegion.getLength();
- if (startOffset != -1) {
- DeleteEdit deletion = createDeletion(doc, startOffset, endOffset);
- rootEdit.addChild(deletion);
- endLineInclusive = doc.getLineOfOffset(startOffset) - 1;
- }
- break;
- }
- }
- }
-
- // Dedent the contents
- if (changeIndentation && startLineInclusive != -1 && endLineInclusive != -1) {
- String indent = AndroidXmlEditor.getIndentAtOffset(doc, getRegion(element)
- .getStartOffset());
- setIndentation(rootEdit, indent, doc, startLineInclusive, endLineInclusive,
- element, skip);
- }
- } finally {
- model.releaseFromRead();
- }
- }
-
- protected void removeIndentation(MultiTextEdit rootEdit, String removeIndent,
- IStructuredDocument doc, int startLineInclusive, int endLineInclusive,
- Element element, List<Element> skip) {
- if (startLineInclusive > endLineInclusive) {
- return;
- }
- int indentLength = removeIndent.length();
- if (indentLength == 0) {
- return;
- }
-
- try {
- for (int line = startLineInclusive; line <= endLineInclusive; line++) {
- IRegion info = doc.getLineInformation(line);
- int lineStart = info.getOffset();
- int lineLength = info.getLength();
- int lineEnd = lineStart + lineLength;
- if (overlaps(lineStart, lineEnd, element, skip)) {
- continue;
- }
- String lineText = getText(lineStart,
- lineStart + Math.min(lineLength, indentLength));
- if (lineText.startsWith(removeIndent)) {
- rootEdit.addChild(new DeleteEdit(lineStart, indentLength));
- }
- }
- } catch (BadLocationException e) {
- AdtPlugin.log(e, null);
- }
- }
-
- protected void setIndentation(MultiTextEdit rootEdit, String indent,
- IStructuredDocument doc, int startLineInclusive, int endLineInclusive,
- Element element, List<Element> skip) {
- if (startLineInclusive > endLineInclusive) {
- return;
- }
- int indentLength = indent.length();
- if (indentLength == 0) {
- return;
- }
-
- try {
- for (int line = startLineInclusive; line <= endLineInclusive; line++) {
- IRegion info = doc.getLineInformation(line);
- int lineStart = info.getOffset();
- int lineLength = info.getLength();
- int lineEnd = lineStart + lineLength;
- if (overlaps(lineStart, lineEnd, element, skip)) {
- continue;
- }
- String lineText = getText(lineStart, lineStart + lineLength);
- int indentEnd = getFirstNonSpace(lineText);
- rootEdit.addChild(new ReplaceEdit(lineStart, indentEnd, indent));
- }
- } catch (BadLocationException e) {
- AdtPlugin.log(e, null);
- }
- }
-
- private int getFirstNonSpace(String s) {
- for (int i = 0; i < s.length(); i++) {
- if (!Character.isWhitespace(s.charAt(i))) {
- return i;
- }
- }
-
- return s.length();
- }
-
- /** Returns true if the given line overlaps any of the given elements */
- private static boolean overlaps(int startOffset, int endOffset,
- Element element, List<Element> overlaps) {
- for (Element e : overlaps) {
- if (e == element) {
- continue;
- }
-
- IndexedRegion region = getRegion(e);
- if (region.getEndOffset() >= startOffset && region.getStartOffset() <= endOffset) {
- return true;
- }
- }
- return false;
- }
-
- protected DeleteEdit createDeletion(IStructuredDocument doc, int startOffset, int endOffset) {
- // Expand to delete the whole line?
- try {
- IRegion info = doc.getLineInformationOfOffset(startOffset);
- int lineBegin = info.getOffset();
- // Is the text on the line leading up to the deletion region,
- // and the text following it, all whitespace?
- boolean deleteLine = true;
- if (lineBegin < startOffset) {
- String prefix = getText(lineBegin, startOffset);
- if (prefix.trim().length() > 0) {
- deleteLine = false;
- }
- }
- info = doc.getLineInformationOfOffset(endOffset);
- int lineEnd = info.getOffset() + info.getLength();
- if (lineEnd > endOffset) {
- String suffix = getText(endOffset, lineEnd);
- if (suffix.trim().length() > 0) {
- deleteLine = false;
- }
- }
- if (deleteLine) {
- startOffset = lineBegin;
- endOffset = Math.min(doc.getLength(), lineEnd + 1);
- }
- } catch (BadLocationException e) {
- AdtPlugin.log(e, null);
- }
-
-
- return new DeleteEdit(startOffset, endOffset - startOffset);
- }
-
- /**
- * Rewrite the edits in the given {@link MultiTextEdit} such that same edits are
- * applied, but the resulting range is also formatted
- */
- protected MultiTextEdit reformat(MultiTextEdit edit, XmlFormatStyle style) {
- String xml = mDelegate.getEditor().getStructuredDocument().get();
- return reformat(xml, edit, style);
- }
-
- /**
- * Rewrite the edits in the given {@link MultiTextEdit} such that same edits are
- * applied, but the resulting range is also formatted
- *
- * @param oldContents the original contents that should be edited by a
- * {@link MultiTextEdit}
- * @param edit the {@link MultiTextEdit} to be applied to some string
- * @param style the formatting style to use
- * @return a new {@link MultiTextEdit} which performs the same edits as the input edit
- * but also reformats the text
- */
- public static MultiTextEdit reformat(String oldContents, MultiTextEdit edit,
- XmlFormatStyle style) {
- IDocument document = new org.eclipse.jface.text.Document();
- document.set(oldContents);
-
- try {
- edit.apply(document);
- } catch (MalformedTreeException e) {
- AdtPlugin.log(e, null);
- return null; // Abort formatting
- } catch (BadLocationException e) {
- AdtPlugin.log(e, null);
- return null; // Abort formatting
- }
-
- String actual = document.get();
-
- // TODO: Try to format only the affected portion of the document.
- // To do that we need to find out what the affected offsets are; we know
- // the MultiTextEdit's affected range, but that is referring to offsets
- // in the old document. Use that to compute offsets in the new document.
- //int distanceFromEnd = actual.length() - edit.getExclusiveEnd();
- //IStructuredModel model = DomUtilities.createStructuredModel(actual);
- //int start = edit.getOffset();
- //int end = actual.length() - distanceFromEnd;
- //int length = end - start;
- //TextEdit format = AndroidXmlFormattingStrategy.format(model, start, length);
- EclipseXmlFormatPreferences formatPrefs = EclipseXmlFormatPreferences.create();
- String formatted = EclipseXmlPrettyPrinter.prettyPrint(actual, formatPrefs, style,
- null /*lineSeparator*/);
-
-
- // Figure out how much of the before and after strings are identical and narrow
- // the replacement scope
- boolean foundDifference = false;
- int firstDifference = 0;
- int lastDifference = formatted.length();
- int start = 0;
- int end = oldContents.length();
-
- for (int i = 0, j = start; i < formatted.length() && j < end; i++, j++) {
- if (formatted.charAt(i) != oldContents.charAt(j)) {
- firstDifference = i;
- foundDifference = true;
- break;
- }
- }
-
- if (!foundDifference) {
- // No differences - the document is already formatted, nothing to do
- return null;
- }
-
- lastDifference = firstDifference + 1;
- for (int i = formatted.length() - 1, j = end - 1;
- i > firstDifference && j > start;
- i--, j--) {
- if (formatted.charAt(i) != oldContents.charAt(j)) {
- lastDifference = i + 1;
- break;
- }
- }
-
- start += firstDifference;
- end -= (formatted.length() - lastDifference);
- end = Math.max(start, end);
- formatted = formatted.substring(firstDifference, lastDifference);
-
- ReplaceEdit format = new ReplaceEdit(start, end - start,
- formatted);
-
- MultiTextEdit newEdit = new MultiTextEdit();
- newEdit.addChild(format);
-
- return newEdit;
- }
-
- protected ViewElementDescriptor getElementDescriptor(String fqcn) {
- AndroidTargetData data = mDelegate.getEditor().getTargetData();
- if (data != null) {
- return data.getLayoutDescriptors().findDescriptorByClass(fqcn);
- }
-
- return null;
- }
-
- /** Create a wizard for this refactoring */
- abstract VisualRefactoringWizard createWizard();
-
- public abstract static class VisualRefactoringDescriptor extends RefactoringDescriptor {
- private final Map<String, String> mArguments;
-
- public VisualRefactoringDescriptor(
- String id, String project, String description, String comment,
- Map<String, String> arguments) {
- super(id, project, description, comment, STRUCTURAL_CHANGE | MULTI_CHANGE);
- mArguments = arguments;
- }
-
- public Map<String, String> getArguments() {
- return mArguments;
- }
-
- protected abstract Refactoring createRefactoring(Map<String, String> args);
-
- @Override
- public Refactoring createRefactoring(RefactoringStatus status) throws CoreException {
- try {
- return createRefactoring(mArguments);
- } catch (NullPointerException e) {
- status.addFatalError("Failed to recreate refactoring from descriptor");
- return null;
- }
- }
- }
-}