package com.android.ide.common.resources.platform;
import com.android.ide.common.api.IAttributeInfo.Format;
+import com.android.ide.common.log.ILogger;
import com.android.ide.common.resources.platform.ViewClassInfo.LayoutParamsInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
-import org.eclipse.core.runtime.IStatus;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
private Document mDocument;
private String mOsAttrsXmlPath;
+
// all attributes that have the same name are supposed to have the same
// parameters so we'll keep a cache of them to avoid processing them twice.
private HashMap<String, AttributeInfo> mAttributeMap;
private final Map<String, DeclareStyleableInfo> mStyleMap =
new HashMap<String, DeclareStyleableInfo>();
- /** Map of all (constant, value) pairs for attributes of format enum or flag.
+ /**
+ * Map of all (constant, value) pairs for attributes of format enum or flag.
* E.g. for attribute name=gravity, this tells us there's an enum/flag called "center"
* with value 0x11.
*/
private Map<String, Map<String, Integer>> mEnumFlagValues;
+ /**
+ * A logger object. Must not be null.
+ */
+ private final ILogger mLog;
+
/**
* Creates a new {@link AttrsXmlParser}, set to load things from the given
* XML file. Nothing has been parsed yet. Callers should call {@link #preload()}
* next.
+ *
+ * @param osAttrsXmlPath The path of the <code>attrs.xml</code> file to parse.
+ * Must not be null. Should point to an existing valid XML document.
+ * @param log A logger object. Must not be null.
*/
- public AttrsXmlParser(String osAttrsXmlPath) {
- this(osAttrsXmlPath, null /* inheritableAttributes */);
+ public AttrsXmlParser(String osAttrsXmlPath, ILogger log) {
+ this(osAttrsXmlPath, null /* inheritableAttributes */, log);
}
/**
* Creates a new {@link AttrsXmlParser} set to load things from the given
- * XML file. If inheritableAttributes is non-null, it must point to a preloaded
+ * XML file.
+ * <p/>
+ * If inheritableAttributes is non-null, it must point to a preloaded
* {@link AttrsXmlParser} which attributes will be used for this one. Since
* already defined attributes are not modifiable, they are thus "inherited".
+ *
+ * @param osAttrsXmlPath The path of the <code>attrs.xml</code> file to parse.
+ * Must not be null. Should point to an existing valid XML document.
+ * @param inheritableAttributes An optional parser with attributes to inherit. Can be null.
+ * If not null, the parser must have had its {@link #preload()} method
+ * invoked prior to being used here.
+ * @param log A logger object. Must not be null.
*/
- public AttrsXmlParser(String osAttrsXmlPath, AttrsXmlParser inheritableAttributes) {
+ public AttrsXmlParser(
+ String osAttrsXmlPath,
+ AttrsXmlParser inheritableAttributes,
+ ILogger log) {
mOsAttrsXmlPath = osAttrsXmlPath;
+ mLog = log;
+
+ assert osAttrsXmlPath != null;
+ assert log != null;
if (inheritableAttributes == null) {
mAttributeMap = new HashMap<String, AttributeInfo>();
}
/**
- * @return The OS path of the attrs.xml file parsed
+ * Returns the OS path of the attrs.xml file parsed.
*/
public String getOsAttrsXmlPath() {
return mOsAttrsXmlPath;
Document doc = getDocument();
if (doc == null) {
- AdtPlugin.log(IStatus.WARNING, "Failed to find %1$s", //$NON-NLS-1$
+ mLog.warning("Failed to find %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
return this;
}
}
if (res == null) {
- AdtPlugin.log(IStatus.WARNING, "Failed to find a <resources> node in %1$s", //$NON-NLS-1$
+ mLog.warning("Failed to find a <resources> node in %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
return this;
}
}
/**
- * Returns a list of all decleare-styleable found in the xml file.
+ * Returns a list of all <code>decleare-styleable</code> found in the XML file.
*/
public Map<String, DeclareStyleableInfo> getDeclareStyleableList() {
return Collections.unmodifiableMap(mStyleMap);
DocumentBuilder builder = factory.newDocumentBuilder();
mDocument = builder.parse(new File(mOsAttrsXmlPath));
} catch (ParserConfigurationException e) {
- AdtPlugin.log(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
+ mLog.error(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
} catch (SAXException e) {
- AdtPlugin.log(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
+ mLog.error(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
} catch (IOException e) {
- AdtPlugin.log(e, "Failed to read XML document %1$s", //$NON-NLS-1$
+ mLog.error(e, "Failed to read XML document %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
}
}
}
/**
- * Finds all the <declare-styleable> and <attr> nodes in the top <resources> node.
+ * Finds all the <declare-styleable> and <attr> nodes
+ * in the top <resources> node.
*/
private void parseResources(Node res) {
formats.add(format);
}
} catch (IllegalArgumentException e) {
- AdtPlugin.log(e, "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
- f, name, getOsAttrsXmlPath());
+ mLog.error(e,
+ "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
+ f, name, getOsAttrsXmlPath());
}
}
}
if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(filter)) {
Node nameNode = child.getAttributes().getNamedItem("name"); //$NON-NLS-1$
if (nameNode == null) {
- AdtPlugin.log(IStatus.WARNING,
+ mLog.warning(
"Missing name attribute in <attr name=\"%s\"><%s></attr>", //$NON-NLS-1$
attrName, filter);
} else {
Node valueNode = child.getAttributes().getNamedItem("value"); //$NON-NLS-1$
if (valueNode == null) {
- AdtPlugin.log(IStatus.WARNING,
- "Missing value attribute in <attr name=\"%s\"><%s name=\"%s\"></attr>", //$NON-NLS-1$
- attrName, filter, name);
+ mLog.warning(
+ "Missing value attribute in <attr name=\"%s\"><%s name=\"%s\"></attr>", //$NON-NLS-1$
+ attrName, filter, name);
} else {
String value = valueNode.getNodeValue();
try {
map.put(name, Integer.valueOf(i));
} catch(NumberFormatException e) {
- AdtPlugin.log(e,
+ mLog.error(e,
"Value in <attr name=\"%s\"><%s name=\"%s\" value=\"%s\"></attr> is not a valid decimal or hexadecimal", //$NON-NLS-1$
attrName, filter, name, value);
}
/**
* Interface used to display warnings/errors while parsing the SDK content.
+ * <p/>
+ * There are a few default implementations available:
+ * <ul>
+ * <li> {@link NullSdkLog} is an implementation that does <em>nothing</em> with the log.
+ * Useful for limited cases where you need to call a class that requires a non-null logging
+ * yet the calling code does not have any mean of reporting logs itself. It can be
+ * acceptable for use a temporary implementation but most of the time that means the caller
+ * code needs to be reworked to take a logger object from its own caller.
+ * </li>
+ * <li> {@link StdSdkLog} is an implementation that dumps the log to {@link System#out} or
+ * {@link System#err}. This is useful for unit tests or code that does not have any GUI.
+ * Apps based on Eclipse or SWT should not use it and should provide a better way to report
+ * to the user.
+ * </li>
+ * <li> ADT has a <code>AdtPlugin</code> which implements a similar interface called
+ * <code>ILogger</code>, useful in case we don't want to pull the whole SdkLib.
+ * </ul>
*/
public interface ISdkLog {
-
+
/**
* Prints a warning message on stdout.
* <p/>
* need to put such a prefix in the format string.
* <p/>
* Implementations should only display warnings in verbose mode.
- *
+ *
* @param warningFormat is an optional error format. If non-null, it will be printed
* using a {@link Formatter} with the provided arguments.
* @param args provides the arguments for warningFormat.
*/
void warning(String warningFormat, Object... args);
-
+
/**
* Prints an error message on stderr.
* <p/>
* need to put such a prefix in the format string.
* <p/>
* Implementation should always display errors, independent of verbose mode.
- *
+ *
* @param t is an optional {@link Throwable} or {@link Exception}. If non-null, it's
* message will be printed out.
* @param errorFormat is an optional error format. If non-null, it will be printed
* @param args provides the arguments for errorFormat.
*/
void error(Throwable t, String errorFormat, Object... args);
-
+
/**
* Prints a message as-is on stdout.
* <p/>
- * Implementation should always display errors, independent of verbose mode.
+ * Implementation can omit printing such messages when not in verbose mode.
* No prefix is used, the message is printed as-is after formatting.
- *
+ *
* @param msgFormat is an optional error format. If non-null, it will be printed
* using a {@link Formatter} with the provided arguments.
* @param args provides the arguments for msgFormat.