/* 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.data;
import com.google.gdata.util.common.xml.XmlNamespace;
import com.google.gdata.util.common.xml.XmlWriter;
import com.google.gdata.client.CoreErrorDomain;
import com.google.gdata.util.Namespaces;
import com.google.gdata.util.ParseException;
import com.google.gdata.util.ServiceConfigurationException;
import com.google.gdata.util.XmlParser;
import org.xml.sax.Attributes;
import java.io.IOException;
import java.io.Reader;
/**
* OpenSearch description document.
* See http://opensearch.a9.com/ for more information.
*
*
*
*/
public class OpenSearchDescriptionDocument extends ExtensionPoint {
public OpenSearchDescriptionDocument() {}
public OpenSearchDescriptionDocument(OpenSearchDescriptionDocument doc) {
url = doc.url;
format = doc.format;
shortName = doc.shortName;
longName = doc.longName;
description = doc.description;
tags = doc.tags;
image = doc.image;
sampleSearch = doc.sampleSearch;
developer = doc.developer;
contact = doc.contact;
attribution = doc.attribution;
syndicationRight = doc.syndicationRight;
adultContent = doc.adultContent;
}
/** The HTTP GET URL at which the search content can be found. */
protected String url;
public final String getUrl() { return url; }
public void setUrl(String v) { url = v; }
/** The XML schema used by the search engine specified by {@code url}. */
protected String format;
public final String getFormat() { return format; }
public void setFormat(String v) { format = v; }
/**
* A brief name that will appear in UI elements that reference this
* search content provider.
*/
protected String shortName;
public final String getShortName() { return shortName; }
public void setShortName(String v) { shortName = v; }
/**
* The name by which this search content provider is referred to in
* hypertext links, etc.
*/
protected String longName;
public final String getLongName() { return longName; }
public void setLongName(String v) { longName = v; }
/** A human readable text description of the search content provider. */
protected String description;
public final String getDescription() { return description; }
public void setDescription(String v) { description = v; }
/**
* A space-delimited set of words that are used as keywords to identify and
* categorize this search content.
*/
protected String tags;
public final String getTags() { return tags; }
public void setTags(String v) { tags = v; }
/**
* A URL that identifies the location of a 64x64-pixel image that can be used
* in association with this search engine.
*/
protected String image;
public final String getImage() { return image; }
public void setImage(String v) { image = v; }
/**
* A search string that should be used when example searches are done against
* this OpenSearch engine.
*/
protected String sampleSearch;
public final String getSampleSearch() { return sampleSearch; }
public void setSampleSearch(String v) { sampleSearch = v; }
/** The developer or maintainer of the OpenSearch feed. */
protected String developer;
public final String getDeveloper() { return developer; }
public void setDeveloper(String v) { developer = v; }
/** An email address at which the developer can be reached. */
protected String contact;
public final String getContact() { return contact; }
public void setContact(String v) { contact = v; }
/** A list of all content sources or platforms that should be credited. */
protected String attribution;
public final String getAttribution() { return attribution; }
public void setAttribution(String v) { attribution = v; }
/**
* The degree to which the search results provided by this search engine can
* be distributed.
*/
protected int syndicationRight = SyndicationRight.OPEN;
public final int getSyndicationRight() { return syndicationRight; }
public void setSyndicationRight(int v) { syndicationRight = v; }
/**
* The SyndicationRight class defines constant values for syndication
* rights types.
*/
public static class SyndicationRight {
/** Search results can be published or re-published without restriction. */
public static final int OPEN = 0;
/**
* Search results can be published on the client site, but not further
* republished.
*/
public static final int LIMITED = 1;
/**
* Search feed may be queried, but the results may not be displayed at the
* client site.
*/
public static final int PRIVATE = 2;
/** Search feed should not be queried. */
public static final int CLOSED = 3;
}
/**
* A boolean flag that must be set if the content provided is not suitable for
* minors.
*/
protected boolean adultContent = false;
public final boolean getAdultContent() { return adultContent; }
public void setAdultContent(boolean v) { adultContent = v; }
/**
* Generates XML.
*
* @param w
* output writer
*
* @throws IOException
*/
public void generate(XmlWriter w) throws IOException {
XmlNamespace openSearchDescNs = Namespaces.getOpenSearchDescNs();
w.startElement(openSearchDescNs, "OpenSearchDescription", null, null);
if (url != null) {
w.simpleElement(openSearchDescNs, "Url", null, url);
}
if (format != null) {
w.simpleElement(openSearchDescNs, "Format", null, format);
}
if (shortName != null) {
w.simpleElement(openSearchDescNs, "ShortName", null, shortName);
}
if (longName != null) {
w.simpleElement(openSearchDescNs, "LongName", null, longName);
}
if (description != null) {
w.simpleElement(openSearchDescNs, "Description", null, description);
}
if (tags != null) {
w.simpleElement(openSearchDescNs, "Tags", null, tags);
}
if (image != null) {
w.simpleElement(openSearchDescNs, "Image", null, image);
}
if (sampleSearch != null) {
w.simpleElement(openSearchDescNs, "SampleSearch", null,
sampleSearch);
}
if (developer != null) {
w.simpleElement(openSearchDescNs, "Developer", null,
developer);
}
if (contact != null) {
w.simpleElement(openSearchDescNs, "Contact", null, contact);
}
if (attribution != null) {
w.simpleElement(openSearchDescNs, "Attribution", null,
attribution);
}
String syndicationRightString;
switch (syndicationRight) {
case SyndicationRight.OPEN:
default:
syndicationRightString = "open";
break;
case SyndicationRight.LIMITED:
syndicationRightString = "limited";
break;
case SyndicationRight.PRIVATE:
syndicationRightString = "private";
break;
case SyndicationRight.CLOSED:
syndicationRightString = "closed";
break;
}
w.simpleElement(openSearchDescNs, "SyndicationRight", null,
syndicationRightString);
if (adultContent) {
w.simpleElement(openSearchDescNs, "AdultContent", null,
"true");
}
w.endElement(openSearchDescNs, "OpenSearchDescription");
}
/**
* Validates that the OpenSearchDescriptionDocument has all required
* properties. The one exception is the <code>url</code> property,
* which is dynamically generated based upon the feed that is queried.
*/
public void validateConfiguration() throws ServiceConfigurationException {
if (format == null) {
throw new ServiceConfigurationException(
CoreErrorDomain.ERR.missingFormat);
}
if (shortName == null) {
throw new ServiceConfigurationException(
CoreErrorDomain.ERR.missingShortName);
}
if (description == null) {
throw new ServiceConfigurationException(
CoreErrorDomain.ERR.missingDescription);
}
if (tags == null) {
throw new ServiceConfigurationException(
CoreErrorDomain.ERR.missingTags);
}
if (contact == null) {
throw new ServiceConfigurationException(
CoreErrorDomain.ERR.missingContact);
}
}
/**
* Parses XML.
*
* @param extProfile
* extension profile
*
* @param reader
* XML input stream
*
* @throws IOException
*
* @throws ParseException
*/
public void parse(ExtensionProfile extProfile, Reader reader)
throws IOException, ParseException {
XmlNamespace openSearchDescNs = Namespaces.getOpenSearchDescNs();
new XmlParser().parse(reader, new Handler(extProfile),
openSearchDescNs.getUri(), "OpenSearchDescription");
}
/**
* XmlParser ElementHandler for {@code openSearchDesc:OpenSearchDescription}
*/
public class Handler extends ExtensionPoint.ExtensionHandler {
public Handler(ExtensionProfile extProfile) {
super(extProfile, OpenSearchDescriptionDocument.class);
}
@Override
public XmlParser.ElementHandler getChildHandler(String namespace,
String localName,
Attributes attrs)
throws ParseException, IOException {
XmlNamespace openSearchDescNs = Namespaces.getOpenSearchDescNs();
if (namespace.equals(openSearchDescNs.getUri())) {
if (localName.equals("Url")) {
ensureNull(url);
return new UrlHandler();
} else if (localName.equals("Format")) {
ensureNull(format);
return new FormatHandler();
} else if (localName.equals("ShortName")) {
ensureNull(shortName);
return new ShortNameHandler();
} else if (localName.equals("LongName")) {
ensureNull(longName);
return new LongNameHandler();
} else if (localName.equals("Description")) {
ensureNull(description);
return new DescriptionHandler();
} else if (localName.equals("Tags")) {
ensureNull(tags);
return new TagsHandler();
} else if (localName.equals("Image")) {
ensureNull(image);
return new ImageHandler();
} else if (localName.equals("SampleSearch")) {
ensureNull(sampleSearch);
return new SampleSearchHandler();
} else if (localName.equals("Developer")) {
ensureNull(developer);
return new DeveloperHandler();
} else if (localName.equals("Contact")) {
ensureNull(contact);
return new ContactHandler();
} else if (localName.equals("Attribution")) {
ensureNull(attribution);
return new AttributionHandler();
} else if (localName.equals("SyndicationRight")) {
return new SyndicationRightHandler();
} else if (localName.equals("AdultContent")) {
return new AdultContentHandler();
}
} else {
return super.getChildHandler(namespace, localName, attrs);
}
return null;
}
private void ensureNull(String s) throws ParseException {
if (s != null) {
throw new ParseException(
CoreErrorDomain.ERR.duplicateValue);
}
}
/** osrsDesc:Url parser. */
private class UrlHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
url = value;
}
}
/** osrsDesc:Format parser. */
private class FormatHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
format = value;
}
}
/** osrsDesc:ShortName parser. */
private class ShortNameHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
shortName = value;
}
}
/** osrsDesc:LongName parser. */
private class LongNameHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
longName = value;
}
}
/** osrsDesc:Description parser. */
private class DescriptionHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
description = value;
}
}
/** osrsDesc:Tags parser. */
private class TagsHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
tags = value;
}
}
/** osrsDesc:Image parser. */
private class ImageHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
image = value;
}
}
/** osrsDesc:SampleSearch parser. */
private class SampleSearchHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
sampleSearch = value;
}
}
/** osrsDesc:Developer parser. */
private class DeveloperHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
developer = value;
}
}
/** osrsDesc:Contact parser. */
private class ContactHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
contact = value;
}
}
/** osrsDesc:Attribution parser. */
private class AttributionHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
attribution = value;
}
}
/** openSearchDesc:SyndicationRight parser. */
private class SyndicationRightHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
if (value.equalsIgnoreCase("open")) {
syndicationRight = SyndicationRight.OPEN;
} else if (value.equalsIgnoreCase("limited")) {
syndicationRight = SyndicationRight.LIMITED;
} else if (value.equalsIgnoreCase("private")) {
syndicationRight = SyndicationRight.PRIVATE;
} else if (value.equalsIgnoreCase("closed")) {
syndicationRight = SyndicationRight.CLOSED;
}
}
}
/** openSearchDesc:AdultContent parser. */
private class AdultContentHandler extends XmlParser.ElementHandler {
@Override
public void processEndElement() {
if (!value.equals("false") &&
!value.equals("FALSE") &&
!value.equals("0") &&
!value.equals("no") &&
!value.equals("NO")) {
adultContent = true;
}
}
}
}
}