/* Copyright (c) 2008 Google Inc. * * 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.google.gdata.util; import com.google.gdata.util.common.xml.XmlNamespace; import com.google.gdata.util.common.xml.XmlWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; /** * Arbitrary self-contained block of XML. * * */ public class XmlBlob { /** * Initial {@code xml:lang} value. This value is typically inherited through * the XML tree. The blob itself may contain overrides. * <p> * * See http://www.w3.org/TR/REC-xml/#sec-lang-tag for more information. */ protected String lang; public String getLang() { return lang; } public void setLang(String v) { lang = v; } /** * Initial {@code xml:base} value. This value is typically inherited through * the XML tree. The blob itself may contain overrides. * <p> * * See http://www.cafeconleche.org/books/xmljava/chapters/ch03s03.html for * more information. */ protected String base; public String getBase() { return base; } public void setBase(String v) { base = v; } /** * Namespace declarations inherited when this blob was parsed but used * within it. */ protected LinkedList<XmlNamespace> namespaces = new LinkedList<XmlNamespace>(); public List<XmlNamespace> getNamespaces() { return namespaces; } public boolean addNamespace(XmlNamespace namespace) { return namespaces.add(namespace); } /** * Contents of the blob. Depending on how the blob was parsed, it may contain * top-level text() nodes mixed together with child elements. */ protected String blob; public String getBlob() { return blob; } public void setBlob(String v) { blob = v; } /** * Contains strings from {@code blob} for full-text indexing. * Valid only when this blob comes from {@link XmlParser}. */ protected String fullText; public String getFullText() { return fullText; } public void setFullText(String v) { fullText = v; } /** Generates an element opening tag containing an XML blob. */ public static void startElement(XmlWriter w, XmlNamespace namespace, String elementName, XmlBlob xml, Collection<XmlWriter.Attribute> additionalAttrs, Collection<XmlNamespace> additionalNs) throws IOException { Collection<XmlWriter.Attribute> attrs; Collection<XmlNamespace> namespaces; if (xml != null) { String lang = xml.getLang(); String base = xml.getBase(); if (lang != null || base != null) { attrs = new ArrayList<XmlWriter.Attribute>(); if (additionalAttrs != null) { attrs.addAll(additionalAttrs); } if (lang != null) { attrs.add(new XmlWriter.Attribute("xml:lang", lang)); } if (base != null) { attrs.add(new XmlWriter.Attribute("xml:base", base)); } } else { assert lang == null && base == null; attrs = additionalAttrs; } List<XmlNamespace> blobNamespaces = xml.getNamespaces(); int additionalNsSize = (additionalNs == null ? 0 : additionalNs.size()); if (blobNamespaces.size() == 0 && additionalNsSize == 0) { namespaces = null; } else { namespaces = new ArrayList<XmlNamespace>(additionalNsSize + blobNamespaces.size()); // Blob namespaces have to go first, because we depend on their aliases // being preserved. If an additional namespace has a conflicting alias, // we want the additional namespace to get an arbitrarily generated // alias, not the blob's. for (XmlNamespace blobNs : blobNamespaces) { namespaces.add(new XmlNamespace(blobNs.getAlias(), blobNs.getUri())); } if (additionalNs != null) { namespaces.addAll(additionalNs); } } } else { assert xml == null; attrs = additionalAttrs; namespaces = additionalNs; } w.startElement(namespace, elementName, attrs, namespaces); } /** Generates an element closing tag containing an XML blob. */ public static void endElement(XmlWriter w, XmlNamespace namespace, String elementName, XmlBlob xml) throws IOException { if (xml != null && xml.getBlob() != null) { w.innerXml(xml.getBlob()); } w.endElement(namespace, elementName); } }