📄 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.data.Extension;import com.google.gdata.data.ExtensionDescription;import com.google.gdata.data.ExtensionProfile;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.HashMap;import java.util.HashSet;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 Manifest}. * * * */public class ExtensionPoint { /** A specification of acceptable extensions within an extension point. */ static public class Manifest { /** Maps (Namespace URI, local name) to corresponding extension data. */ final Map<Pair<String, String>, ExtensionDescription> supportedExtensions = new HashMap<Pair<String, String>, ExtensionDescription>(); /** * Specifies whether the extension point supports arbitrary XML * ({code xs:any}). If it does, it is available through {@link xmlBlob}. */ boolean arbitraryXml = false; /** * Returns the Map from namespace/localname String pairs to supporting * Extension class and manifest information. */ public Map<Pair<String, String>, ExtensionDescription> getSupportedExtensions() { return Collections.unmodifiableMap(supportedExtensions); } /** * Retrieves a collection of namespace declarations for all possible * extensions based on this manifest. */ Collection<XmlWriter.Namespace> getNamespaceDecls() { Collection<XmlWriter.Namespace> nsDecls = new HashSet<XmlWriter.Namespace>(); for (ExtensionDescription extDescription: supportedExtensions.values()) { nsDecls.add(extDescription.getNamespace()); } return nsDecls; } } /** Collection of non-repeating extensions. */ private Map<Class, Extension> nonRepeatingExtensionMap = new HashMap<Class, Extension>(); /** Collection of repeating extensions. */ private Map<Class, List<Extension>> repeatingExtensionMap = new HashMap<Class, List<Extension>>(); /** Arbitrary XML (unrecognized extensions). */ protected XmlBlob xmlBlob = new XmlBlob(); /** Manifest for this instance. Filled on-demand. */ private Manifest 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); } /** 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; } /** Internal helper method. */ private 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. */ private 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -