Home | History | Annotate | Download | only in gle2
      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.editors.layout.gle2;
     18 
     19 import com.android.ide.common.rendering.api.LayoutLog;
     20 import com.android.ide.eclipse.adt.AdtPlugin;
     21 
     22 import org.eclipse.core.runtime.IStatus;
     23 
     24 import java.util.ArrayList;
     25 import java.util.HashSet;
     26 import java.util.List;
     27 import java.util.Set;
     28 
     29 /**
     30  * A {@link LayoutLog} which records the problems it encounters and offers them as a
     31  * single summary at the end
     32  */
     33 class RenderLogger extends LayoutLog {
     34     static final String TAG_MISSING_DIMENSION = "missing.dimension";     //$NON-NLS-1$
     35 
     36     private final String mName;
     37     private List<String> mFidelityWarnings;
     38     private List<String> mWarnings;
     39     private List<String> mErrors;
     40     private boolean mHaveExceptions;
     41     private List<String> mTags;
     42     private static Set<String> sIgnoredFidelityWarnings;
     43 
     44     /** Construct a logger for the given named layout */
     45     RenderLogger(String name) {
     46         mName = name;
     47     }
     48 
     49     /**
     50      * Are there any logged errors or warnings during the render?
     51      *
     52      * @return true if there were problems during the render
     53      */
     54     public boolean hasProblems() {
     55         return mFidelityWarnings != null || mErrors != null || mWarnings != null ||
     56             mHaveExceptions;
     57     }
     58 
     59     /**
     60      * Returns a (possibly multi-line) description of all the problems
     61      *
     62      * @param includeFidelityWarnings if true, include fidelity warnings in the problem
     63      *            summary
     64      * @return a string describing the rendering problems
     65      */
     66     public String getProblems(boolean includeFidelityWarnings) {
     67         StringBuilder sb = new StringBuilder();
     68 
     69         if (mErrors != null) {
     70             for (String error : mErrors) {
     71                 sb.append(error).append('\n');
     72             }
     73         }
     74 
     75         if (mWarnings != null) {
     76             for (String warning : mWarnings) {
     77                 sb.append(warning).append('\n');
     78             }
     79         }
     80 
     81         if (includeFidelityWarnings && mFidelityWarnings != null) {
     82             sb.append("The graphics preview in the layout editor may not be accurate:\n");
     83             for (String warning : mFidelityWarnings) {
     84                 sb.append("* ");
     85                 sb.append(warning).append('\n');
     86             }
     87         }
     88 
     89         if (mHaveExceptions) {
     90             sb.append("Exception details are logged in Window > Show View > Error Log");
     91         }
     92 
     93         return sb.toString();
     94     }
     95 
     96     /**
     97      * Returns the fidelity warnings
     98      *
     99      * @return the fidelity warnings
    100      */
    101     public List<String> getFidelityWarnings() {
    102         return mFidelityWarnings;
    103     }
    104 
    105     // ---- extends LayoutLog ----
    106 
    107     @Override
    108     public void error(String tag, String message, Object data) {
    109         String description = describe(message);
    110 
    111         AdtPlugin.log(IStatus.ERROR, "%1$s: %2$s", mName, description);
    112 
    113         // Workaround: older layout libraries don't provide a tag for this error
    114         if (tag == null && message != null
    115                 && message.startsWith("Failed to find style ")) { //$NON-NLS-1$
    116             tag = LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR;
    117         }
    118 
    119         addError(tag, description);
    120     }
    121 
    122     @Override
    123     public void error(String tag, String message, Throwable throwable, Object data) {
    124         String description = describe(message);
    125         AdtPlugin.log(throwable, "%1$s: %2$s", mName, description);
    126         if (throwable != null) {
    127             if (throwable instanceof ClassNotFoundException) {
    128                 // The project callback is given a chance to resolve classes,
    129                 // and when it fails, it will record it in its own list which
    130                 // is displayed in a special way (with action hyperlinks etc).
    131                 // Therefore, include these messages in the visible render log,
    132                 // especially since the user message from a ClassNotFoundException
    133                 // is really not helpful (it just lists the class name without
    134                 // even mentioning that it is a class-not-found exception.)
    135                 return;
    136             }
    137 
    138             mHaveExceptions = true;
    139         }
    140 
    141         addError(tag, description);
    142     }
    143 
    144     @Override
    145     public void warning(String tag, String message, Object data) {
    146         String description = describe(message);
    147         AdtPlugin.log(IStatus.WARNING, "%1$s: %2$s", mName, description);
    148 
    149         if (TAG_RESOURCES_FORMAT.equals(tag)) {
    150             if (description.equals("You must supply a layout_width attribute.")       //$NON-NLS-1$
    151                 || description.equals("You must supply a layout_height attribute.")) {//$NON-NLS-1$
    152                 tag = TAG_MISSING_DIMENSION;
    153             }
    154         }
    155 
    156         addWarning(tag, description);
    157     }
    158 
    159     @Override
    160     public void fidelityWarning(String tag, String message, Throwable throwable, Object data) {
    161         if (sIgnoredFidelityWarnings != null && sIgnoredFidelityWarnings.contains(message)) {
    162             return;
    163         }
    164 
    165         String description = describe(message);
    166         AdtPlugin.log(throwable, "%1$s: %2$s", mName, description);
    167         if (throwable != null) {
    168             mHaveExceptions = true;
    169         }
    170 
    171         addFidelityWarning(tag, description);
    172     }
    173 
    174     /**
    175      * Ignore the given render fidelity warning for the current session
    176      *
    177      * @param message the message to be ignored for this session
    178      */
    179     public static void ignoreFidelityWarning(String message) {
    180         if (sIgnoredFidelityWarnings == null) {
    181             sIgnoredFidelityWarnings = new HashSet<String>();
    182         }
    183         sIgnoredFidelityWarnings.add(message);
    184     }
    185 
    186     private String describe(String message) {
    187         StringBuilder sb = new StringBuilder();
    188         if (message != null) {
    189             if (sb.length() > 0) {
    190                 sb.append(": ");
    191             }
    192             sb.append(message);
    193         }
    194         return sb.toString();
    195     }
    196 
    197     private void addWarning(String tag, String description) {
    198         if (mWarnings == null) {
    199             mWarnings = new ArrayList<String>();
    200         } else if (mWarnings.contains(description)) {
    201             // Avoid duplicates
    202             return;
    203         }
    204         mWarnings.add(description);
    205         addTag(tag);
    206     }
    207 
    208     private void addError(String tag, String description) {
    209         if (mErrors == null) {
    210             mErrors = new ArrayList<String>();
    211         } else if (mErrors.contains(description)) {
    212             // Avoid duplicates
    213             return;
    214         }
    215         mErrors.add(description);
    216         addTag(tag);
    217     }
    218 
    219     private void addFidelityWarning(String tag, String description) {
    220         if (mFidelityWarnings == null) {
    221             mFidelityWarnings = new ArrayList<String>();
    222         } else if (mFidelityWarnings.contains(description)) {
    223             // Avoid duplicates
    224             return;
    225         }
    226         mFidelityWarnings.add(description);
    227         addTag(tag);
    228     }
    229 
    230     // ---- Tags ----
    231 
    232     private void addTag(String tag) {
    233         if (tag != null) {
    234             if (mTags == null) {
    235                 mTags = new ArrayList<String>();
    236             }
    237             mTags.add(tag);
    238         }
    239     }
    240 
    241     /**
    242      * Returns true if the given tag prefix has been seen
    243      *
    244      * @param prefix the tag prefix to look for
    245      * @return true iff any tags with the given prefix was seen during the render
    246      */
    247     public boolean seenTagPrefix(String prefix) {
    248         if (mTags != null) {
    249             for (String tag : mTags) {
    250                 if (tag.startsWith(prefix)) {
    251                     return true;
    252                 }
    253             }
    254         }
    255 
    256         return false;
    257     }
    258 
    259     /**
    260      * Returns true if the given tag has been seen
    261      *
    262      * @param tag the tag to look for
    263      * @return true iff the tag was seen during the render
    264      */
    265     public boolean seenTag(String tag) {
    266         if (mTags != null) {
    267             return mTags.contains(tag);
    268         } else {
    269             return false;
    270         }
    271     }
    272 }
    273