Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.refactorings.core;
     18 
     19 import static com.android.SdkConstants.ANDROID_URI;
     20 import static com.android.SdkConstants.ATTR_NAME;
     21 import static com.android.xml.AndroidManifest.ATTRIBUTE_BACKUP_AGENT;
     22 import static com.android.xml.AndroidManifest.ATTRIBUTE_MANAGE_SPACE_ACTIVITY;
     23 import static com.android.xml.AndroidManifest.ATTRIBUTE_PARENT_ACTIVITY_NAME;
     24 import static com.android.xml.AndroidManifest.ATTRIBUTE_TARGET_ACTIVITY;
     25 
     26 import com.android.annotations.NonNull;
     27 import com.android.annotations.Nullable;
     28 import com.android.ide.eclipse.adt.AdtPlugin;
     29 import com.android.xml.AndroidManifest;
     30 
     31 import org.eclipse.core.runtime.CoreException;
     32 import org.eclipse.core.runtime.IStatus;
     33 import org.eclipse.jface.text.BadLocationException;
     34 import org.eclipse.jface.text.IDocument;
     35 import org.eclipse.wst.sse.core.StructuredModelManager;
     36 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
     37 import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
     38 import org.w3c.dom.Attr;
     39 import org.w3c.dom.Element;
     40 
     41 import java.io.IOException;
     42 import java.io.UnsupportedEncodingException;
     43 
     44 /**
     45  * The utility class for android refactoring
     46  *
     47  */
     48 @SuppressWarnings("restriction")
     49 public class RefactoringUtil {
     50 
     51     private static boolean sRefactorAppPackage = false;
     52 
     53     /**
     54      * Releases SSE read model; saves SSE model if exists edit model
     55      * Called in dispose method of refactoring change classes
     56      *
     57      * @param model the SSE model
     58      * @param document the document
     59      */
     60     public static void fixModel(IStructuredModel model, IDocument document) {
     61         if (model != null) {
     62             model.releaseFromRead();
     63         }
     64         model = null;
     65         if (document == null) {
     66             return;
     67         }
     68         try {
     69             model = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
     70             if (model != null) {
     71                 model.save();
     72             }
     73         } catch (UnsupportedEncodingException e1) {
     74             // ignore
     75         } catch (IOException e1) {
     76             // ignore
     77         } catch (CoreException e1) {
     78             // ignore
     79         } finally {
     80             if (model != null) {
     81                 model.releaseFromEdit();
     82             }
     83         }
     84     }
     85 
     86     /**
     87      * Logs the info message
     88      *
     89      * @param message the message
     90      */
     91     public static void logInfo(String message) {
     92         AdtPlugin.log(IStatus.INFO, AdtPlugin.PLUGIN_ID, message);
     93     }
     94 
     95     /**
     96      * Logs the the exception
     97      *
     98      * @param e the exception
     99      */
    100     public static void log(Throwable e) {
    101         AdtPlugin.log(e, e.getMessage());
    102     }
    103 
    104     /**
    105      * @return true if Rename/Move package needs to change the application package
    106      * default is false
    107      *
    108      */
    109     public static boolean isRefactorAppPackage() {
    110         return sRefactorAppPackage;
    111     }
    112 
    113     /**
    114      * @param refactorAppPackage true if Rename/Move package needs to change the application package
    115      */
    116     public static void setRefactorAppPackage(boolean refactorAppPackage) {
    117         RefactoringUtil.sRefactorAppPackage = refactorAppPackage;
    118     }
    119 
    120     /**
    121      * Returns the range of the attribute value in the given document
    122      *
    123      * @param attr the attribute to look up
    124      * @param document the document containing the attribute
    125      * @return the range of the value text, not including quotes, in the document
    126      */
    127     public static int getAttributeValueRangeStart(
    128             @NonNull Attr attr,
    129             @NonNull IDocument document) {
    130         IndexedRegion region = (IndexedRegion) attr;
    131         int potentialStart = attr.getName().length() + 2; // + 2: add ="
    132         String text;
    133         try {
    134             text = document.get(region.getStartOffset(),
    135                     region.getEndOffset() - region.getStartOffset());
    136         } catch (BadLocationException e) {
    137             return -1;
    138         }
    139         String value = attr.getValue();
    140         int index = text.indexOf(value, potentialStart);
    141         if (index != -1) {
    142             return region.getStartOffset() + index;
    143         } else {
    144             return -1;
    145         }
    146     }
    147 
    148     /**
    149      * Returns the start of the tag name of the given element
    150      *
    151      * @param element the element to look up
    152      * @param document the document containing the attribute
    153      * @return the index of the start tag in the document
    154      */
    155     public static int getTagNameRangeStart(
    156             @NonNull Element element,
    157             @NonNull IDocument document) {
    158         IndexedRegion region = (IndexedRegion) element;
    159         int potentialStart = 1; // add '<'
    160         String text;
    161         try {
    162             text = document.get(region.getStartOffset(),
    163                     region.getEndOffset() - region.getStartOffset());
    164         } catch (BadLocationException e) {
    165             return -1;
    166         }
    167         int index = text.indexOf(element.getTagName(), potentialStart);
    168         if (index != -1) {
    169             return region.getStartOffset() + index;
    170         } else {
    171             return -1;
    172         }
    173     }
    174 
    175     /**
    176      * Returns whether the given manifest attribute should be considered to describe
    177      * a class name. These will be eligible for refactoring when classes are renamed
    178      * or moved.
    179      *
    180      * @param attribute the manifest attribute
    181      * @return true if this attribute can describe a class
    182      */
    183     public static boolean isManifestClassAttribute(@NonNull Attr attribute) {
    184         return isManifestClassAttribute(
    185                 attribute.getOwnerElement().getTagName(),
    186                 attribute.getNamespaceURI(),
    187                 attribute.getLocalName());
    188     }
    189 
    190     /**
    191      * Returns whether the given manifest attribute should be considered to describe
    192      * a class name. These will be eligible for refactoring when classes are renamed
    193      * or moved.
    194      *
    195      * @param tag the tag, if known
    196      * @param uri the attribute namespace, if any
    197      * @param name the attribute local name, if any
    198      * @return true if this attribute can describe a class
    199      */
    200     public static boolean isManifestClassAttribute(
    201             @Nullable String tag,
    202             @Nullable String uri,
    203             @Nullable String name) {
    204         if (name == null) {
    205             return false;
    206         }
    207 
    208         if ((name.equals(ATTR_NAME)
    209                 && (AndroidManifest.NODE_ACTIVITY.equals(tag)
    210                         || AndroidManifest.NODE_APPLICATION.equals(tag)
    211                         || AndroidManifest.NODE_INSTRUMENTATION.equals(tag)
    212                         || AndroidManifest.NODE_PROVIDER.equals(tag)
    213                         || AndroidManifest.NODE_SERVICE.equals(tag)
    214                         || AndroidManifest.NODE_RECEIVER.equals(tag)))
    215                 || name.equals(ATTRIBUTE_TARGET_ACTIVITY)
    216                 || name.equals(ATTRIBUTE_MANAGE_SPACE_ACTIVITY)
    217                 || name.equals(ATTRIBUTE_BACKUP_AGENT)
    218                 || name.equals(ATTRIBUTE_PARENT_ACTIVITY_NAME)) {
    219             return ANDROID_URI.equals(uri);
    220         }
    221 
    222         return false;
    223     }
    224 }
    225