📄 extensionpoint.java
字号:
/* Copyright (c) 2006 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.data;import com.google.gdata.util.common.base.Pair;import com.google.gdata.util.common.xml.XmlWriter;import com.google.gdata.util.ParseException;import com.google.gdata.util.XmlBlob;import com.google.gdata.util.XmlNamespace;import com.google.gdata.util.XmlParser;import com.google.gdata.util.XmlParser.ElementHandler;import org.xml.sax.Attributes;import java.io.IOException;import java.io.StringReader;import java.io.StringWriter;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;/** * Base class for GData data types that support hosting extensions. * <p> * For example, a calendar {@code <atom:entry>} supports hosting * {@code <gd:when>}. * <p> * The set of accepted extensions is defined within {@link ExtensionManifest}. * * * */public class ExtensionPoint extends AbstractExtension { /** Collection of non-repeating extensions. Uses {@link LinkedHashMap} in * order to provide a predictable generation output order based upon * insertion order. */ private Map<Class, Extension> nonRepeatingExtensionMap = new LinkedHashMap<Class, Extension>(); /** Collection of repeating extensions. Uses {@link LinkedHashMap} in * order to provide a predictable generation output order based upon * insertion order. */ private Map<Class, List<Extension>> repeatingExtensionMap = new LinkedHashMap<Class, List<Extension>>(); /** Arbitrary XML (unrecognized extensions). */ protected XmlBlob xmlBlob = new XmlBlob(); /** Manifest for this instance. Filled on-demand. */ private ExtensionManifest manifest; /** * Simple constructor to create a new (empty) ExtensionPoint. */ public ExtensionPoint() {}; /** * Simple copy constructor that does a shallow copy of extension and * manifest data from an existing ExtensionPoint to the constructed * instance. */ protected ExtensionPoint(ExtensionPoint sourcePoint) { // WARNING: ANY NON-STATIC FIELDS ADDED ABOVE NEED TO BE COPIED HERE. nonRepeatingExtensionMap = sourcePoint.nonRepeatingExtensionMap; repeatingExtensionMap = sourcePoint.repeatingExtensionMap; xmlBlob = sourcePoint.xmlBlob; manifest = sourcePoint.manifest; } /** * Declares the set of expected Extension types for an ExtensionPoint * within the target extension profile. The base implementation * does not declare any extensions, but can be overridden by specific * types of ExtensionPoints that always contain a well-defined set * of extensions. * * @param extProfile * the ExtensionProfile to initialize. */ public void declareExtensions(ExtensionProfile extProfile) { // The default implementation does not register any extensions. } /** Retrieves a non-repeating extension or {@code null} if not present. */ public <T extends Extension> T getExtension(Class<T> extensionClass) { return (T)nonRepeatingExtensionMap.get(extensionClass); } /** * Returns an unmodifiable collection of non-repeating extensions in this * ExtensionPoint. * * @return Collection of non-repeating extensions. */ public Collection<Extension> getExtensions() { return Collections.unmodifiableCollection( nonRepeatingExtensionMap.values()); } /** Retrieves a repeating extension list (an empty list if not present). */ public <T extends Extension> List<T> getRepeatingExtension( Class<T> extensionClass) { List<T> ret = (List<T>)repeatingExtensionMap.get(extensionClass); if (ret == null) { ret = new ArrayList<T>(); repeatingExtensionMap.put(extensionClass, (List<Extension>)ret); } return ret; } /** * Returns an unmodifiable collection of lists of repeating extensions in * this ExtensionPoint. The Extensions that are of the same type * are grouped together in lists within the collection. * * @return Collection of lists of repeating extensions. */ public Collection<List<Extension>> getRepeatingExtensions() { return Collections.unmodifiableCollection( repeatingExtensionMap.values()); } /** Internal helper method. */ protected boolean addExtension(Extension ext, Class extClass) { if (nonRepeatingExtensionMap.containsKey(extClass)) { return false; } nonRepeatingExtensionMap.put(extClass, ext); return true; } /** Adds an extension object. */ public void addExtension(Extension ext) { addExtension(ext, ext.getClass()); } /** Sets an extension object. If one exists of this type, it's replaced. */ public void setExtension(Extension ext) { nonRepeatingExtensionMap.remove(ext.getClass()); addExtension(ext, ext.getClass()); } /** Internal helper method. */ protected void addRepeatingExtension(Extension ext, Class extClass) { List<Extension> extList = repeatingExtensionMap.get(extClass); if (extList == null) { extList = new ArrayList<Extension>(); } extList.add(ext); repeatingExtensionMap.put(extClass, extList); } /** Adds a repeating extension object. */ public void addRepeatingExtension(Extension ext) { addRepeatingExtension(ext, ext.getClass()); } /** Removes an extension object. */ public void removeExtension(Extension ext) { nonRepeatingExtensionMap.remove(ext.getClass()); } /** Removes an extension object based on its class. */ public void removeExtension(Class extensionClass) { nonRepeatingExtensionMap.remove(extensionClass); } /** Removes a repeating extension object. */ public void removeRepeatingExtension(Extension ext) { List<Extension> extList = repeatingExtensionMap.get(ext.getClass()); if (extList == null) { return; } extList.remove(ext); } /** * Retrieves the XML blob containing arbitrary (unrecognized) * extensions. */ public XmlBlob getXmlBlob() { return xmlBlob; } /** Sets the XML blob containing arbitrary (unrecognized) extensions. */ public void setXmlBlob(XmlBlob xmlBlob) { this.xmlBlob = xmlBlob; } /** * Generates an XML blob containing all recognized and unrecognized * extensions. This can be used by applications that persist data in * a store that might be accessed by other applications--ones that * don't necessarily recognize the same set of extensions. */ public XmlBlob generateCumulativeXmlBlob(ExtensionProfile extProfile) throws IOException { XmlBlob cumulative = new XmlBlob(); Collection<XmlNamespace> namespaces = cumulative.getNamespaces(); StringWriter w = new StringWriter(); XmlWriter xw = new XmlWriter(w); if (xmlBlob != null) { cumulative.setLang(xmlBlob.getLang()); cumulative.setBase(xmlBlob.getBase()); namespaces.addAll(xmlBlob.getNamespaces()); w.write(xmlBlob.getBlob()); } if (manifest != null) { for (XmlWriter.Namespace ns: manifest.getNamespaceDecls()) { XmlNamespace newNs = new XmlNamespace(ns.getAlias(), ns.getUri()); if (!namespaces.contains(newNs)) { namespaces.add(newNs); } } } for (Extension ext: nonRepeatingExtensionMap.values()) { ext.generate(xw, extProfile); } for (List<Extension> extList: repeatingExtensionMap.values()) { xw.startRepeatingElement(); for (Extension ext: extList) { ext.generate(xw, extProfile); } xw.endRepeatingElement(); } cumulative.setBlob(w.toString()); return cumulative; } /** * Reverses {@link #generateCumulativeXmlBlob(ExtensionProfile)}. * This operation overwrites the current contents of this extension * point. */ public void parseCumulativeXmlBlob(XmlBlob xmlBlob, ExtensionProfile extProfile, Class extendedClass) throws IOException, ParseException { this.xmlBlob = new XmlBlob(); nonRepeatingExtensionMap.clear(); repeatingExtensionMap.clear(); // Prepare a fake XML document from the blob. StringWriter sw = new StringWriter(); XmlWriter w = new XmlWriter(sw); XmlBlob.startElement(w, null, "CUMULATIVE_BLOB", xmlBlob, null, null); XmlBlob.endElement(w, null, "CUMULATIVE_BLOB", xmlBlob); // Now parse it. StringReader sr = new StringReader(sw.toString()); XmlParser parser = new XmlParser(); parser.parse(sr, new CumulativeBlobHandler(extProfile, extendedClass), "", "CUMULATIVE_BLOB"); } /** Parser class for cumulative XML blobs. */ public class CumulativeBlobHandler extends ElementHandler { public CumulativeBlobHandler(ExtensionProfile extProfile, Class extendedClass) throws IOException { this.extProfile = extProfile; this.extendedClass = extendedClass; initializeArbitraryXml(extProfile, extendedClass, this); } private final ExtensionProfile extProfile; private final Class extendedClass; public ElementHandler getChildHandler(String namespace, String localName, Attributes attrs) throws ParseException, IOException { // Try ExtensionPoint. It returns {@code null} if there's no handler. ElementHandler extensionHandler = getExtensionHandler(extProfile, extendedClass, namespace, localName, attrs); if (extensionHandler != null) { return extensionHandler; } return super.getChildHandler(namespace, localName, attrs); } } /** Retrieves the manifest for the specified class. */ protected ExtensionManifest getManifest( ExtensionProfile extProfile, Class<? extends ExtensionPoint> extendedClass) { if (manifest == null) { manifest = extProfile.getManifest(extendedClass); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -