/* Copyright (c) 2007 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.api.gbase.client;
import com.google.gdata.util.common.xml.XmlWriter;
import com.google.gdata.data.AttributeHelper;
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.XmlParser;
import org.xml.sax.Attributes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* Java representation for the gm:attributes tag for in the itemtypes feed.
*/
@ExtensionDescription.Default(
nsAlias = GoogleBaseNamespaces.GM_ALIAS,
nsUri = GoogleBaseNamespaces.GM_URI,
localName = "attributes")
public class GmAttributes implements Extension {
private final List<GmAttribute> attributes =
new ArrayList<GmAttribute>();
private final Set<GoogleBaseAttributeId> attributeIds =
new LinkedHashSet<GoogleBaseAttributeId>();
/**
* Gets an unmodifiable list of GoogleBaseAttributeId objects.
*
* @return attribute list, which might be empty
* @deprecated use {@link #getAttributes()} instead.
*/
public List<GoogleBaseAttributeId> getAttributeIds() {
return Collections.unmodifiableList(
new ArrayList<GoogleBaseAttributeId>(attributeIds));
}
/**
* Gets an unmodifiable collection of GmAttribute objects.
*
* @return attribute list, which might be empty
*/
public Collection<GmAttribute> getAttributes() {
return Collections.unmodifiableCollection(attributes);
}
/**
* Adds a new attribute to the list with no importance specified.
*
* @param name attribute name
* @param type attribute type, may be null
* @throws NullPointerException if name is null
* @deprecated use
* {@link #addAttribute(GoogleBaseAttributeId, GmAttribute.Importance)}
* instead. This method will be removed in a future release
*/
public void addAttribute(String name, GoogleBaseAttributeType type) {
GoogleBaseAttributeId attributeId = new GoogleBaseAttributeId(name, type);
addAttribute(attributeId, null);
}
/**
* Adds a new attribute to the list.
*
* <p> Note: The importance parameter should not be null. The current
* implementation allows null values for loadind old attributes persisted on
* client side. The null check will be enabled in a future release.
*
* @param attributeId the id for this attribute
* @param importance attribute importance, may be null if no importance is
* defined
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if an attribute with the same name and
* type has already been added
*/
public void addAttribute(GoogleBaseAttributeId attributeId,
GmAttribute.Importance importance) {
if (attributeIds.contains(attributeId)) {
throw new IllegalArgumentException("Attribute id already registered " +
"in the attributes group " + attributeId);
}
attributes.add(new GmAttribute(attributeId, importance));
attributeIds.add(attributeId);
}
/** Generate the XML representation for this tag. */
public void generate(XmlWriter w, ExtensionProfile extProfile)
throws IOException {
if (attributes.isEmpty()) {
// Nothing to write
return;
}
w.startElement(GoogleBaseNamespaces.GM, "attributes", null, null);
w.startRepeatingElement();
for (GmAttribute attribute : attributes) {
List<XmlWriter.Attribute> attributes =
new ArrayList<XmlWriter.Attribute>();
GoogleBaseAttributeId id = attribute.getAttributeId();
attributes.add(new XmlWriter.Attribute("name", id.getName()));
if (id.getType() != null) {
attributes.add(new XmlWriter.Attribute("type", id.getType().getName()));
}
if (attribute.getImportance() != null) {
attributes.add(new XmlWriter.Attribute("importance",
attribute.getImportance().getXmlValue()));
}
w.simpleElement(GoogleBaseNamespaces.GM, "attribute", attributes, null);
}
w.endRepeatingElement();
w.endElement();
}
/** Creates a parser for this tag. */
public XmlParser.ElementHandler getHandler(ExtensionProfile extProfile,
String namespace, String localName, Attributes attrs)
throws ParseException, IOException {
// Reset the list
attributes.clear();
return new XmlParser.ElementHandler() {
/** Parses gm:attribute sub-elements. */
@Override
public XmlParser.ElementHandler getChildHandler(String namespace,
String localName, Attributes attrs)
throws ParseException, IOException {
if (namespace.equals(GoogleBaseNamespaces.GM_URI)
&& "attribute".equals(localName)) {
AttributeHelper helper = new AttributeHelper(attrs);
String nameAttr = helper.consume("name", true);
GoogleBaseAttributeType typeAttr = GoogleBaseAttributeType
.getInstance(helper.consume("type", false));
GmAttribute.Importance importanceAttr = helper
.consumeEnum("importance", false, GmAttribute.Importance.class);
GoogleBaseAttributeId attributeId =
new GoogleBaseAttributeId(nameAttr, typeAttr);
addAttribute(attributeId, importanceAttr);
helper.assertAllConsumed();
return new XmlParser.ElementHandler();
} else {
return super.getChildHandler(namespace, localName, attrs);
}
}
};
}
/**
* The information defining an attribute, as contained by the gm:attribute
* element in the itemtypes feed.
*/
public static class GmAttribute {
/**
* Enumeration defining the importance levels that an attribute can have.
*/
public enum Importance {
/**
* The attribute is very important in defining the characteristics of an
* item. In the future, the presence of the required attributes might be
* checked for the item types defined by Google.
*/
REQUIRED,
/**
* The attribute is important for providing good quality for an item, but
* the item is meaningful even if this attribute is not specified.
* Providing a value for a recommended attribute increases the chances of
* showing the item in a Google search.
*/
RECOMMENDED,
/**
* The attribute usually provides behavioral or other meta information for
* the item it belongs to. This information is not very important for
* direct attribute searches, but can affect where and when an attribute
* is shown.
*/
OPTIONAL,
/**
* The attribute is deprecated and should not be used when creating new
* items.
*/
DEPRECATED;
/** The string defining this instance in an Xml document. */
private final String xmlValue;
Importance() {
xmlValue = this.name().toLowerCase();
}
/** Gets the importance level as in an Xml document. */
String getXmlValue() {
return xmlValue;
}
}
/** The attribute id identifying this attribute. */
private final GoogleBaseAttributeId attributeId;
/** The importance for this attribute. */
private final Importance importance;
/**
* Creates a GmAttribute instance with the specified id and importance. A
* null importance value should be provided when no importance is defined.
*
* @param attributeId the id of the attribute
* @param importance the importance, or null if no information is available
* @throws NullPointerException if the attributeId is null.
*/
public GmAttribute(GoogleBaseAttributeId attributeId, Importance importance)
{
if (attributeId == null) {
throw new NullPointerException("AttributeId is null.");
}
this.attributeId = attributeId;
this.importance = importance;
}
/**
* Returns the id of this attribute.
*/
public GoogleBaseAttributeId getAttributeId() {
return attributeId;
}
/**
* Returns the importance for this attribute, or null if not defined.
*/
public Importance getImportance() {
return importance;
}
}
}