| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed 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 com.motorola.studio.android.model.resources.parser; |
| |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.apache.xerces.parsers.DOMParser; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.osgi.util.NLS; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Text; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS; |
| import com.motorola.studio.android.common.exception.AndroidException; |
| import com.motorola.studio.android.common.log.StudioLogger; |
| import com.motorola.studio.android.model.resources.types.AbstractResourceNode; |
| import com.motorola.studio.android.model.resources.types.AbstractResourceNode.NodeType; |
| import com.motorola.studio.android.model.resources.types.AbstractSimpleNameResourceNode; |
| import com.motorola.studio.android.model.resources.types.ColorNode; |
| import com.motorola.studio.android.model.resources.types.DimenNode; |
| import com.motorola.studio.android.model.resources.types.DrawableNode; |
| import com.motorola.studio.android.model.resources.types.IResourceTypesAttributes; |
| import com.motorola.studio.android.model.resources.types.ResourcesNode; |
| import com.motorola.studio.android.model.resources.types.StringNode; |
| import com.motorola.studio.android.model.resources.types.UnknownNode; |
| |
| /** |
| * Abstract class that implements methods to parse a resource file |
| */ |
| public class AbstractResourceFileParser implements IResourceTypesAttributes |
| { |
| /** |
| * The root nodes of the resource file |
| */ |
| protected final List<AbstractResourceNode> rootNodes; |
| |
| /** |
| * Default constructor |
| */ |
| public AbstractResourceFileParser() |
| { |
| rootNodes = new LinkedList<AbstractResourceNode>(); |
| } |
| |
| /** |
| * Parses an IDocument object containing a resource file content |
| * |
| * @param document the IDocument object |
| * @param sourceFileName The resource file that is being parsed |
| * |
| * @throws SAXException When a parsing error occurs |
| * @throws IOException When a reading error occurs |
| */ |
| public void parseDocument(IDocument document, String sourceFileName) throws AndroidException |
| { |
| Element element; |
| DOMParser domParser = new DOMParser(); |
| |
| rootNodes.clear(); |
| |
| StringReader stringReader = null; |
| try |
| { |
| stringReader = new StringReader(document.get()); |
| domParser.parse(new InputSource(stringReader)); |
| } |
| catch (SAXException e) |
| { |
| String errMsg = |
| NLS.bind(CodeUtilsNLS.EXC_AbstractResourceFileParser_ErrorParsingTheXMLFile, |
| sourceFileName, e.getLocalizedMessage()); |
| StudioLogger.error(AbstractResourceFileParser.class, errMsg, e); |
| throw new AndroidException(errMsg); |
| } |
| catch (IOException e) |
| { |
| String errMsg = |
| NLS.bind(CodeUtilsNLS.EXC_AbstractResourceFileParser_ErrorReadingTheXMLContent, |
| sourceFileName, e.getLocalizedMessage()); |
| StudioLogger.error(AbstractResourceFileParser.class, errMsg, e); |
| throw new AndroidException(errMsg); |
| } |
| finally |
| { |
| if (stringReader != null) |
| { |
| stringReader.close(); |
| } |
| } |
| |
| element = domParser.getDocument().getDocumentElement(); |
| parseNode(element, null); |
| } |
| |
| /** |
| * Parses a XML Node |
| * |
| * @param element The XML Node |
| * @param rootNode The XML Node parent (An AbstractResourceNode that has been parsed) |
| */ |
| private void parseNode(Node node, AbstractResourceNode rootNode) |
| { |
| if (node instanceof Element) |
| { |
| Element element = (Element) node; |
| AbstractResourceNode arNode; |
| Node xmlNode; |
| NodeList xmlChildNodes; |
| NamedNodeMap attributes = element.getAttributes(); |
| NodeType nodeType = identifyNode(element); |
| |
| switch (nodeType) |
| { |
| case Resources: |
| arNode = parseResourcesNode(); |
| break; |
| case String: |
| arNode = parseStringNode(attributes); |
| break; |
| case Color: |
| arNode = parseColorNode(attributes); |
| break; |
| case Dimen: |
| arNode = parseDimenNode(attributes); |
| break; |
| case Drawable: |
| arNode = parseDrawableNode(attributes); |
| break; |
| default: |
| arNode = parseUnknownNode(node); |
| } |
| |
| // Adds the child nodes |
| xmlChildNodes = element.getChildNodes(); |
| |
| for (int i = 0; i < xmlChildNodes.getLength(); i++) |
| { |
| xmlNode = xmlChildNodes.item(i); |
| parseNode(xmlNode, arNode); |
| } |
| |
| if (rootNode == null) |
| { |
| rootNodes.add(arNode); |
| } |
| else |
| { |
| rootNode.addChildNode(arNode); |
| } |
| } |
| else if ((node instanceof Text) && (rootNode != null)) |
| { |
| if ((node.getNodeValue() != null) && (node.getNodeValue().trim().length() > 0)) |
| { |
| if (rootNode instanceof AbstractSimpleNameResourceNode) |
| { |
| AbstractSimpleNameResourceNode asnrNode = |
| (AbstractSimpleNameResourceNode) rootNode; |
| if (asnrNode.getNodeValue() == null) |
| { |
| asnrNode.setNodeValue(node.getNodeValue()); |
| } |
| } |
| else |
| { |
| UnknownNode unknownNode = (UnknownNode) rootNode; |
| if (unknownNode.getNodeValue() == null) |
| { |
| unknownNode.setNodeValue(node.getNodeValue()); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Identifies an XML Node type as an AbstractResourceNode type. |
| * |
| * @param xmlNode The XML Node |
| * @return The corresponding AndroidManifestNode type to the XML Node |
| */ |
| private NodeType identifyNode(Element xmlNode) |
| { |
| String nodeName = xmlNode.getNodeName(); |
| NodeType identifiedType = AbstractResourceNode.getNodeType(nodeName); |
| return identifiedType; |
| } |
| |
| /** |
| * Parses a <resources> node |
| * |
| * @return An AbstractResourceNode object that represents the <resources> node |
| */ |
| private AbstractResourceNode parseResourcesNode() |
| { |
| return new ResourcesNode(); |
| } |
| |
| /** |
| * Parses a <string> node |
| * |
| * @param attributes the node attributes list |
| * @return An AbstractResourceNode object that represents the <string> node |
| */ |
| private AbstractResourceNode parseStringNode(NamedNodeMap attributes) |
| { |
| StringNode arNode = new StringNode(""); |
| Node attribute; |
| String attrName, attrValue; |
| |
| for (int i = 0; i < attributes.getLength(); i++) |
| { |
| attribute = attributes.item(i); |
| |
| attrName = attribute.getNodeName(); |
| attrValue = attribute.getNodeValue(); |
| |
| if (attrName.equalsIgnoreCase(ATTR_NAME)) |
| { |
| arNode.setName(attrValue); |
| } |
| else |
| { |
| arNode.addUnknownAttribute(attrName, attrValue); |
| } |
| } |
| |
| return arNode; |
| } |
| |
| /** |
| * Parses a <color> node |
| * |
| * @param attributes the node attributes list |
| * @return An AbstractResourceNode object that represents the <color> node |
| */ |
| private AbstractResourceNode parseColorNode(NamedNodeMap attributes) |
| { |
| ColorNode arNode = new ColorNode(""); |
| Node attribute; |
| String attrName, attrValue; |
| |
| for (int i = 0; i < attributes.getLength(); i++) |
| { |
| attribute = attributes.item(i); |
| |
| attrName = attribute.getNodeName(); |
| attrValue = attribute.getNodeValue(); |
| |
| if (attrName.equalsIgnoreCase(ATTR_NAME)) |
| { |
| arNode.setName(attrValue); |
| } |
| else |
| { |
| arNode.addUnknownAttribute(attrName, attrValue); |
| } |
| } |
| |
| return arNode; |
| } |
| |
| /** |
| * Parses a <dimen> node |
| * |
| * @param attributes the node attributes list |
| * @return An AbstractResourceNode object that represents the <diment> node |
| */ |
| private AbstractResourceNode parseDimenNode(NamedNodeMap attributes) |
| { |
| DimenNode arNode = new DimenNode(""); |
| Node attribute; |
| String attrName, attrValue; |
| |
| for (int i = 0; i < attributes.getLength(); i++) |
| { |
| attribute = attributes.item(i); |
| |
| attrName = attribute.getNodeName(); |
| attrValue = attribute.getNodeValue(); |
| |
| if (attrName.equalsIgnoreCase(ATTR_NAME)) |
| { |
| arNode.setName(attrValue); |
| } |
| else |
| { |
| arNode.addUnknownAttribute(attrName, attrValue); |
| } |
| } |
| |
| return arNode; |
| } |
| |
| /** |
| * Parses a <drawable> node |
| * |
| * @param attributes the node attributes list |
| * @return An AbstractResourceNode object that represents the <drawable> node |
| */ |
| private AbstractResourceNode parseDrawableNode(NamedNodeMap attributes) |
| { |
| DrawableNode arNode = new DrawableNode(""); |
| Node attribute; |
| String attrName, attrValue; |
| |
| for (int i = 0; i < attributes.getLength(); i++) |
| { |
| attribute = attributes.item(i); |
| |
| attrName = attribute.getNodeName(); |
| attrValue = attribute.getNodeValue(); |
| |
| if (attrName.equalsIgnoreCase(ATTR_NAME)) |
| { |
| arNode.setName(attrValue); |
| } |
| else |
| { |
| arNode.addUnknownAttribute(attrName, attrValue); |
| } |
| } |
| |
| return arNode; |
| } |
| |
| /** |
| * Parses an unknown node |
| * |
| * @param node The xml node |
| * @return An AbstractResourceNode object that represents the unknown node |
| */ |
| private AbstractResourceNode parseUnknownNode(Node node) |
| { |
| UnknownNode arNode = new UnknownNode(node.getNodeName()); |
| NamedNodeMap attributes = node.getAttributes(); |
| Node attribute; |
| String attrName, attrValue; |
| |
| for (int i = 0; i < attributes.getLength(); i++) |
| { |
| attribute = attributes.item(i); |
| |
| attrName = attribute.getNodeName(); |
| attrValue = attribute.getNodeValue(); |
| |
| arNode.addUnknownAttribute(attrName, attrValue); |
| } |
| |
| return arNode; |
| } |
| } |