/* 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.api.gbase.client;
import com.google.gdata.util.common.xml.XmlWriter;
import com.google.gdata.util.common.xml.XmlWriter.Namespace;
import com.google.gdata.data.DateTime;
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.Iterator;
import java.util.List;
/**
* Keeps track of attributes in the g: namespace.
*
* This class extends the Google data API with some knowledge about
* the g: (Google Base attributes) namespace.
*
* The attributes are stored in a list as {@link GoogleBaseAttribute}s
* Accessing GoogleBaseAttribute directly is possible, but usually not
* recommended.
*
* Many methods are available in this class that will perform
* the necessary type conversion from GoogleBaseAttribute to
* String, Integer, Float, and {@link DateTime}.
*
* Shortcuts exist for a few well-known attributes.
*
* You usually get such an object using
* {@link GoogleBaseEntry#getGoogleBaseAttributes()}.
*
* This class can be registered in an
* {@link com.google.gdata.data.ExtensionProfile} using
* {@link #DESCRIPTION} and then accessed from an
* {@link com.google.gdata.data.ExtensionPoint} using
* {@link com.google.gdata.data.ExtensionPoint#getExtension(Class)}.
*
*/
public class GoogleBaseAttributesExtension implements Extension {
/**
* A description for this extension, to pass to an
* {@link com.google.gdata.data.ExtensionProfile}.
*/
public static final ExtensionDescription DESCRIPTION;
/**
* Attribute {@code <g:label>}.
*
* @see #getLabels()
* @see #addLabel(String)
*/
public static final String LABEL_ATTRIBUTE = "label";
/**
* Attribute {@code <g:item_type>}.
*
* @see #getItemType()
* @see #setItemType(String)
*/
public static final String ITEM_TYPE_ATTRIBUTE = "item type";
/**
* Attribute {@code <g:expiration_date>}.
*
* @see #getExpirationDate()
* @see #setExpirationDate(DateTime)
*/
public static final String EXPIRATION_DATE_ATTRIBUTE = "expiration date";
/**
* Attribute {@code <g:image_link>}.
*
* @see #getImageLink()
* @see #getImageLinks()
* @see #addImageLink(String)
*/
public static final String IMAGE_LINK_ATTRIBUTE = "image link";
/**
* Attribute {@code <g:payment_accepted>}.
*
* @see #getPaymentMethods()
* @see #addPaymentMethod(String)
*/
public static final String PAYMENT_METHOD_ATTRIBUTE = "payment accepted";
/**
* Attribute {@code <g:price>}.
*
* @see #getPrice()
* @see #setPrice(NumberUnit)
* @see #setPrice(float, String)
*/
public static final String PRICE_ATTRIBUTE = "price";
/**
* Attribute {@code <g:location>}.
*
* @see #getLocation()
* @see #setLocation(String)
*/
public static final String LOCATION_ATTRIBUTE = "location";
/**
* Attribute {@code <g:price_type>}.
*
* @see #getPriceType()
* @see #setPriceType(String)
*/
public static final String PRICE_TYPE_ATTRIBUTE = "price type";
/**
* Attribute {@code <g:quantity>}.
*
* @see #getQuantity()
* @see #setQuantity(int)
*/
public static final String QUANTITY_ATTRIBUTE = "quantity";
/**
* Attribute {@code <g:price_units>}.
*
* @see #getPriceUnits()
* @see #setPriceUnits(String)
*/
public static final String PRICE_UNITS_ATTRIBUTE = "price units";
/**
* Attribute {@code <g:shipping>}.
*
* @see #getShipping()
* @see #addShipping(Shipping)
*/
public static final String SHIPPING_ATTRIBUTE = "shipping";
/**
* Attribute {@code <g:tax>}.
*
* @see #getTax()
* @see #addTax(Tax)
*/
public static final String TAX_ATTRIBUTE = "tax";
/**
* Attribute {@code <g:tax_percent>}.
*
* @see #getTax()
* @see #addTax(Tax)
* @deprecated use {@link #TAX_ATTRIBUTE} instead
*/
@Deprecated
public static final String TAX_PERCENT_ATTRIBUTE = "tax percent";
/**
* Attribute {@code <g:tax_region>}.
*
* @see #getTax()
* @see #addTax(Tax)
* @deprecated use {@link #TAX_ATTRIBUTE} instead
*/
@Deprecated
public static final String TAX_REGION_ATTRIBUTE = "tax region";
/**
* Attribute {@code <g:delivery_radius>}.
*
* @see #getDeliveryRadius()
* @see #setDeliveryRadius(NumberUnit)
* @see #setDeliveryRadius(float, String)
*/
public static final String DELIVERY_RADIUS_ATTRIBUTE = "delivery radius";
/**
* Attribute {@code <g:pickup>}.
*
* @see #getPickup()
* @see #setPickup(boolean)
*/
public static final String PICKUP_ATTRIBUTE = "pickup";
/**
* Attribute {@code <g:delivery_notes>}.
*
* @see #getDeliveryNotes()
* @see #setDeliveryNotes(String)
*/
public static final String DELIVERY_NOTES_ATTRIBUTE = "delivery notes";
/**
* Attribute {@code <g:payment_notes>}.
*
* @see #getPaymentNotes()
* @see #setPaymentNotes(String)
*/
public static final String PAYMENT_NOTES_ATTRIBUTE = "payment notes";
/**
* Attribute {@code <g:application>}.
*
* @see #getApplication()
* @see #setApplication(String)
*/
public static final String APPLICATION_ATTRIBUTE = "application";
/**
* Attribute {@code <g:customer_id>}.
*
* @see #getCustomerId()
*/
public static final String CUSTOMER_ID = "customer id";
/** Meta attribute {@code gm:adjusted_name}. */
static final String GM_ADJUSTED_NAME_ATTRIBUTE = "adjusted_name";
/** Meta attribute {@code gm:adjusted_value}. */
static final String GM_ADJUSTED_VALUE_ATTRIBUTE = "adjusted_value";
/** Meta attribute {@code gm:thumbnail}. */
static final String GM_THUMBNAIL_ATTRIBUTE = "thumbnail";
/**
* All the attributes available for the current
* {@link com.google.gdata.data.ExtensionPoint} in this extension
* namespace.
*
* Several {@link com.google.api.gbase.client.GoogleBaseAttribute}
* might have the same name and even the same value. Order is
* conserved, but should not be significant.
*/
private final List<GoogleBaseAttribute> attributes =
new ArrayList<GoogleBaseAttribute>();
static {
ExtensionDescription desc = new ExtensionDescription();
desc.setExtensionClass(GoogleBaseAttributesExtension.class);
desc.setNamespace(GoogleBaseNamespaces.G);
desc.setLocalName("*");
desc.setRepeatable(false);
desc.setAggregate(true);
DESCRIPTION = desc;
}
/**
* Gets the labels set for the entry.
*
* @return a collection of strings, which might be
* empty but not null
*/
public Collection<? extends String> getLabels() {
return getTextAttributeValues(LABEL_ATTRIBUTE);
}
/**
* Adds a label to the entry.
*
* @param value
*/
public void addLabel(String value) {
addTextAttribute(LABEL_ATTRIBUTE, value);
}
/** Gets the item type. */
public String getItemType() {
return getTextAttribute(ITEM_TYPE_ATTRIBUTE);
}
/** Sets the item type. */
public void setItemType(String value) {
removeAttributes(ITEM_TYPE_ATTRIBUTE, GoogleBaseAttributeType.TEXT);
addTextAttribute(ITEM_TYPE_ATTRIBUTE, value);
}
/** Gets the date and time at which the entry expires. */
public DateTime getExpirationDate() {
return getDateTimeAttribute(EXPIRATION_DATE_ATTRIBUTE);
}
/** Sets the date at which the entry expires. */
public void setExpirationDate(DateTime date) {
removeAttributes(EXPIRATION_DATE_ATTRIBUTE,
GoogleBaseAttributeType.DATE_TIME);
addDateTimeAttribute(EXPIRATION_DATE_ATTRIBUTE, date);
}
/** Gets the first URL to an image representing this item. */
public String getImageLink() {
return getUrlAttribute(IMAGE_LINK_ATTRIBUTE);
}
/** Gets all URLs to images representing this item. */
public List<? extends String> getImageLinks() {
return getAttributeValuesAsString(IMAGE_LINK_ATTRIBUTE,
GoogleBaseAttributeType.URL);
}
/** Adds an image URL. */
public void addImageLink(String link) {
addUrlAttribute(IMAGE_LINK_ATTRIBUTE, link);
}
/**
* Gets a collection of accepted payment methods (Cash, WireTransfer, ...).
*
* @return a collection of strings, which might be empty but not null.
*/
public Collection<? extends String> getPaymentMethods() {
return getTextAttributeValues(PAYMENT_METHOD_ATTRIBUTE);
}
/**
* Adds an accepted payment method.
*/
public void addPaymentMethod(String method) {
addTextAttribute(PAYMENT_METHOD_ATTRIBUTE, method);
}
/**
* Gets the price of the item.
*
* @return a price (value and currency) or null
*/
public NumberUnit<Float> getPrice() {
return getFloatUnitAttribute(PRICE_ATTRIBUTE);
}
/**
* Sets the price of the item.
*
* @param value
*/
public void setPrice(NumberUnit<Float> value) {
removeAttributes(PRICE_ATTRIBUTE);
addFloatUnitAttribute(PRICE_ATTRIBUTE, value);
}
/**
* Sets the price of the item.
*
* @param value
* @param currency
*/
public void setPrice(float value, String currency) {
setPrice(new NumberUnit<Float>(value, currency));
}
/**
* Gets the location.
*/
public String getLocation() {
return getLocationAttribute(LOCATION_ATTRIBUTE);
}
/**
* Sets the location.
*/
public void setLocation(String value) {
removeAttributes(LOCATION_ATTRIBUTE);
addLocationAttribute(LOCATION_ATTRIBUTE, value);
}
/** Sets price type. */
public void setPriceType(String type) {
removeAttributes(PRICE_TYPE_ATTRIBUTE);
addTextAttribute(PRICE_TYPE_ATTRIBUTE, type);
}
/** Gets price type. */
public String getPriceType() {
return getTextAttribute(PRICE_TYPE_ATTRIBUTE);
}
/** Sets quantity. */
public void setQuantity(int value) {
removeAttributes(QUANTITY_ATTRIBUTE);
addIntAttribute(QUANTITY_ATTRIBUTE, value);
}
/** Gets quantity, or null if not set. */
public Integer getQuantity() {
return getIntAttribute(QUANTITY_ATTRIBUTE);
}
/** Sets price units. */
public void setPriceUnits(String value) {
removeAttributes(PRICE_UNITS_ATTRIBUTE);
addTextAttribute(PRICE_UNITS_ATTRIBUTE, value);
}
/** Gets price units. */
public String getPriceUnits() {
return getTextAttribute(PRICE_UNITS_ATTRIBUTE);
}
/** Adds shipping attribute. */
public void addShipping(Shipping shipping) {
addShippingAttribute(SHIPPING_ATTRIBUTE, shipping);
}
/** Gets shipping attributes. */
public Collection<? extends Shipping> getShipping() {
return getShippingAttributes(SHIPPING_ATTRIBUTE);
}
/** Adds tax attribute. */
public void addTax(Tax tax) {
addTaxAttribute(TAX_ATTRIBUTE, tax);
}
/** Gets tax attributes. */
public Collection<? extends Tax> getTax() {
return getTaxAttributes(TAX_ATTRIBUTE);
}
/**
* Sets tax percent attribute.
*
* @deprecated use {@link #addTax(Tax)} instead
*/
@Deprecated
public void setTaxPercent(float taxPercent) {
removeAttributes(TAX_PERCENT_ATTRIBUTE);
addFloatAttribute(TAX_PERCENT_ATTRIBUTE, taxPercent);
}
/**
* Gets tax percent attribute, or null.
*
* @deprecated use {@link #getTax()} instead
*/
@Deprecated
public Float getTaxPercent() {
return getFloatAttribute(TAX_PERCENT_ATTRIBUTE);
}
/**
* Sets tax region attribute.
*
* @deprecated use {@link #addTax(Tax)} instead
*/
@Deprecated
public void setTaxRegion(String region) {
removeAttributes(TAX_REGION_ATTRIBUTE);
addTextAttribute(TAX_REGION_ATTRIBUTE, region);
}
/**
* Gets tax region attribute.
*
* @deprecated use {@link #getTax()} instead
*/
@Deprecated
public String getTaxRegion() {
return getTextAttribute(TAX_REGION_ATTRIBUTE);
}
/** Sets delivery radius. */
public void setDeliveryRadius(float value, String unit) {
setDeliveryRadius(new NumberUnit<Float>(value, unit));
}
/** Sets delivery radius. */
public void setDeliveryRadius(NumberUnit<Float> value) {
removeAttributes(DELIVERY_RADIUS_ATTRIBUTE);
addFloatUnitAttribute(DELIVERY_RADIUS_ATTRIBUTE, value);
}
/** Gets delivery radius. */
public NumberUnit<Float> getDeliveryRadius() {
return getFloatUnitAttribute(DELIVERY_RADIUS_ATTRIBUTE);
}
/** Sets pickup attribute. */
public void setPickup(boolean pickup) {
removeAttributes(PICKUP_ATTRIBUTE, GoogleBaseAttributeType.BOOLEAN);
addBooleanAttribute(PICKUP_ATTRIBUTE, pickup);
}
/** Gets pickup attribute, or null. */
public Boolean getPickup() {
return getBooleanAttribute(PICKUP_ATTRIBUTE);
}
/** Sets delivery notes attribute. */
public void setDeliveryNotes(String notes) {
removeAttributes(DELIVERY_NOTES_ATTRIBUTE, GoogleBaseAttributeType.TEXT);
addTextAttribute(DELIVERY_NOTES_ATTRIBUTE, notes);
}
/** Gets delivery notes attribute */
public String getDeliveryNotes() {
return getTextAttribute(DELIVERY_NOTES_ATTRIBUTE);
}
/** Sets payment notes attribute. */
public void setPaymentNotes(String notes) {
removeAttributes(PAYMENT_NOTES_ATTRIBUTE, GoogleBaseAttributeType.TEXT);
addTextAttribute(PAYMENT_NOTES_ATTRIBUTE, notes);
}
/** Gets payment notes attribute */
public String getPaymentNotes() {
return getTextAttribute(PAYMENT_NOTES_ATTRIBUTE);
}
public Integer getCustomerId() {
return getIntAttribute(CUSTOMER_ID);
}
/**
* Gets a list of all the attributes available in the extension
* namespace at the current {@link com.google.gdata.data.ExtensionPoint}.
*
* Attributes might be repeated.
*
* @return a list of {@link com.google.api.gbase.client.GoogleBaseAttribute},
* which might be empty but not null
*/
public List<? extends GoogleBaseAttribute> getAttributes() {
return attributes;
}
/**
* Gets the first attribute with a certain name.
*
* In most cases, there might be more than one attribute
* with the same name. This method will ignore extra
* attributes. Use {@link #getAttributes(String)} to make sure
* you get all of them.
*
* @param name attribute name
* @return one {@link com.google.api.gbase.client.GoogleBaseAttribute}
* or null if no attribute was found with this name
*/
public GoogleBaseAttribute getAttribute(String name) {
return getAttribute(name, null);
}
/**
* Gets the first attribute with a certain name and type.
*
* In most cases, there might be more than one attribute
* with the same name and type. This method will ignore extra
* attributes. Use {@link #getAttributes(String)} to make sure
* you get all of them.
*
* @param name attribute name
* @param type attribute type (null to ignore the type)
* @return one {@link com.google.api.gbase.client.GoogleBaseAttribute}
* or null if no attribute was found with this name
*/
public GoogleBaseAttribute getAttribute(String name, GoogleBaseAttributeType type) {
for (GoogleBaseAttribute attr : attributes) {
if (hasNameAndType(attr, name, type)) {
return attr;
}
}
return null;
}
private boolean hasNameAndType(GoogleBaseAttribute attr, String name,
GoogleBaseAttributeType type) {
GoogleBaseAttributeType subtype = attr.getAttributeId().getType();
return name.equals(attr.getAttributeId().getName()) &&
(type == null || subtype != null && type.isSupertypeOf(subtype));
}
/**
* Gets all the attributes with a certain name and type.
*
* @param name attribute name
* @param type attribute type, null to ignore the type
* @return a list of {@link com.google.api.gbase.client.GoogleBaseAttribute},
* which might be empty but not null
*/
public List<? extends GoogleBaseAttribute> getAttributes(String name,
GoogleBaseAttributeType type) {
List<GoogleBaseAttribute> retval = new ArrayList<GoogleBaseAttribute>();
for (GoogleBaseAttribute attr : attributes) {
if (hasNameAndType(attr, name, type)) {
retval.add(attr);
}
}
return retval;
}
/**
* Gets all the attributes with a certain name and type.
*
* @param name attribute name
* @return a list of {@link com.google.api.gbase.client.GoogleBaseAttribute},
* which might be empty but not null
*/
public List<? extends GoogleBaseAttribute> getAttributes(String name) {
return getAttributes(name, null);
}
/**
* Adds an attribute to the list.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param attribute
* @return the attribute passed as parameter
*/
public GoogleBaseAttribute addAttribute(GoogleBaseAttribute attribute) {
attributes.add(attribute);
return attribute;
}
/**
* Removes an attribute from the list.
*
* @param value
*/
public void removeAttribute(GoogleBaseAttribute value) {
attributes.remove(value);
}
/**
* Removes all attributes with a certain name from the list.
*
* @param name name of the attributes that should be removed
*/
public void removeAttributes(String name) {
removeAttributes(name, null);
}
/**
* Removes all attributes with a certain name and
* type from the list.
*
* @param name name of the attributes that should be removed
* @param type attribute type, null to ignore the type
*/
public void removeAttributes(String name, GoogleBaseAttributeType type) {
Iterator<GoogleBaseAttribute> iter = attributes.iterator();
while (iter.hasNext()) {
GoogleBaseAttribute attribute = iter.next();
if (hasNameAndType(attribute, name, type)) {
iter.remove();
}
}
}
/**
* Removes all attributes from the list.
*/
public void clearAttributes() {
attributes.clear();
}
/**
* Gets the first value of a specific attribute, as a string.
*
* If it makes sense for the attribute to appear more
* than once, you might consider calling
* {@link #getTextAttributeValues(String)} instead.
*
* This method checks the type of the attribute
* that is being queried. Use
* {@link #getAttributeAsString(String, GoogleBaseAttributeType)}
* if you would like to get the value of non-string attributes.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
*/
public String getTextAttribute(String name) {
return getAttributeAsString(name, GoogleBaseAttributeType.TEXT);
}
/**
* Gets the first value of a specific reference attribute.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#REFERENCE}.
*
* @param name attribute name
* @return value of the attribute or null if no reference attribute
* with this name was found on the list
*/
public String getReferenceAttribute(String name) {
return getAttributeAsString(name, GoogleBaseAttributeType.REFERENCE);
}
/**
* Gets the string representation of the first
* attribute with matching name and type.
*
* This method does not check the type of the attributes
* that are being queried. It just returns what it finds.
*
* @param name attribute name
* @param type attribute type, null to ignore the type
* @return the string representation of the first matching
* attribute or null if none was found
*/
private String getAttributeAsString(String name,
GoogleBaseAttributeType type) {
GoogleBaseAttribute attribute = getAttribute(name, type);
if (attribute == null) {
return null;
}
return attribute.getValueAsString();
}
/**
* Gets all the values of a specific attribute, as a list
* of strings.
*
* This method checks the type of the attribute
* that are being queried. Use
* {@link #getAttributeAsString(String, GoogleBaseAttributeType)}
* if you would like to get the value non-string attributes.
*
* @param attributeName
* @return a list of strings, which might be empty but
* not null
*/
public List<String> getTextAttributeValues(String attributeName) {
return getAttributeValuesAsString(attributeName,
GoogleBaseAttributeType.TEXT);
}
/**
* Gets the string representation of all attributes with matching
* names and types.
*
* @param name attribute name
* @param type attribute type, null to ignore the type
* @return a list of strings, which might be empty but not null
*/
private List<String> getAttributeValuesAsString(
String name, GoogleBaseAttributeType type) {
List<? extends GoogleBaseAttribute> labels =
getAttributes(name, type);
List<String> retval = new ArrayList<String>(labels.size());
for (GoogleBaseAttribute label : labels) {
retval.add(label.getValueAsString());
}
return retval;
}
/**
* Gets the first value of a specific attribute, as a Float.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#FLOAT}.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public Float getFloatAttribute(String name) {
return ConversionUtil.toFloat(
getAttributeAsString(name, GoogleBaseAttributeType.FLOAT));
}
/**
* Gets the first value of a specific attribute, as an Integer.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#INT}.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public Integer getIntAttribute(String name) {
return ConversionUtil.toInteger(
getAttributeAsString(name,GoogleBaseAttributeType.INT));
}
/**
* Gets the first value of a specific attribute, as a Number.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#NUMBER}.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public Number getNumberAttribute(String name) {
GoogleBaseAttribute attr =
getAttribute(name, GoogleBaseAttributeType.NUMBER);
return ConversionUtil.extractNumber(attr);
}
/**
* Gets the first value of a specific attribute, as an Boolean.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#BOOLEAN}.
*
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
*/
public Boolean getBooleanAttribute(String name) {
return ConversionUtil.toBoolean(
getAttributeAsString(name, GoogleBaseAttributeType.BOOLEAN));
}
/**
* Gets the first value of a specific attribute, as a date and a time.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#DATE_TIME}.
*
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public DateTime getDateTimeAttribute(String name) {
return ConversionUtil.toDateOrDateTime(
getAttributeAsString(name, GoogleBaseAttributeType.DATE_TIME));
}
/**
* Gets the first value of a specific attribute, as a date.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#DATE_TIME} and
* {@link GoogleBaseAttributeType#DATE}.
*
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public DateTime getDateAttribute(String name) {
return ConversionUtil.toDateOrDateTime(
getAttributeAsString(name, GoogleBaseAttributeType.DATE));
}
/**
* Gets the first value of a specific attribute, as a date/dateTime
* range.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#DATE_TIME},
* {@link GoogleBaseAttributeType#DATE} and
* {@link GoogleBaseAttributeType#DATE_TIME_RANGE}.
*
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public DateTimeRange getDateRangeAttribute(String name) {
GoogleBaseAttribute attribute =
getAttribute(name, GoogleBaseAttributeType.DATE_TIME_RANGE);
return ConversionUtil.extractDateTimeRange(attribute);
}
/**
* Gets the first value of a specific attribute, as an url.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#URL}.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
*/
public String getUrlAttribute(String name) {
return getAttributeAsString(name, GoogleBaseAttributeType.URL);
}
/**
* Gets the first value of a specific attribute, as an integer,
* followed by a unit name.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#INT_UNIT}.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public NumberUnit<Integer> getIntUnitAttribute(String name) {
return ConversionUtil.toIntUnit(
getAttributeAsString(name, GoogleBaseAttributeType.INT_UNIT));
}
/**
* Gets the first value of a specific attribute, as an float,
* followed by a unit name.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#FLOAT_UNIT}.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public NumberUnit<Float> getFloatUnitAttribute(String name) {
return ConversionUtil.toFloatUnit(
getAttributeAsString(name, GoogleBaseAttributeType.FLOAT_UNIT));
}
/**
* Gets the first value of a specific attribute, as a Number,
* followed by a unit name.
*
* This method only takes into account attributes of type
* {@link GoogleBaseAttributeType#NUMBER_UNIT},
* {@link GoogleBaseAttributeType#INT_UNIT} or
* {@link GoogleBaseAttributeType#FLOAT_UNIT}.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public NumberUnit<? extends Number> getNumberUnitAttribute(String name) {
return ConversionUtil.extractNumberUnit(
getAttribute(name, GoogleBaseAttributeType.NUMBER_UNIT));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#TEXT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addTextAttribute(String name, String value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.TEXT,
value));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#REFERENCE}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addReferenceAttribute(String name, String value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.REFERENCE, value));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#INT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addIntAttribute(String name, int value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.INT,
Integer.toString(value)));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#FLOAT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addFloatAttribute(String name, float value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.FLOAT,
Float.toString(value)));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#NUMBER}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addNumberAttribute(String name, Number value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.NUMBER,
value.toString()));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#INT_UNIT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value
* @param unit
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addIntUnitAttribute(String name, int value, String unit) {
return addIntUnitAttribute(name, new NumberUnit<Integer>(value, unit));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#INT_UNIT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addIntUnitAttribute(String name,
NumberUnit<Integer> value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.INT_UNIT, value.toString()));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#FLOAT_UNIT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value
* @param unit
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addFloatUnitAttribute(String name,
float value,
String unit) {
return addFloatUnitAttribute(name, new NumberUnit<Float>(value, unit));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#FLOAT_UNIT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addFloatUnitAttribute(String name,
NumberUnit<Float> value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.FLOAT_UNIT, value.toString()));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#NUMBER_UNIT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value
* @param unit
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addNumberUnitAttribute(String name,
Number value,
String unit) {
return addNumberUnitAttribute(name, new NumberUnit<Number>(value, unit));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#NUMBER_UNIT}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addNumberUnitAttribute(String name,
NumberUnit<Number> value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.NUMBER_UNIT, value.toString()));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#DATE}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param date attribute value
* @return the attribute object that has been created and added to the item
* @exception IllegalArgumentException if the attribute value is
* not only a date, but a date and a time (see
* {@link com.google.gdata.data.DateTime#isDateOnly()})
*/
public GoogleBaseAttribute addDateAttribute(String name, DateTime date) {
if (!date.isDateOnly()) {
throw new IllegalArgumentException("DateTime should be only a date, " +
"NOT a date and a time. Call addDateTimeAttribute() instead.");
}
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.DATE,
date.toString()));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#DATE_TIME}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param dateTime attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addDateTimeAttribute(String name,
DateTime dateTime) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.DATE_TIME, dateTime.toString()));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#URL}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addUrlAttribute(String name, String value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.URL,
value));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#BOOLEAN}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param value attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addBooleanAttribute(String name, boolean value) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.BOOLEAN, Boolean.toString(value)));
}
/** Adds group attribute. */
public void addGroupAttribute(String groupName, Group group) {
addAttribute(ConversionUtil.createAttribute(groupName, group));
}
/**
* Gets the first value of a specific attribute, as a
* {@link com.google.api.gbase.client.Group}.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the value and try
* and convert it.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
*/
public Group getGroupAttribute(String name) {
GoogleBaseAttribute value = getAttribute(name);
if (value == null) {
return null;
}
return ConversionUtil.extractGroup(value);
}
/**
* Gets all the values of a specific attribute, as a collection of
* {@link com.google.api.gbase.client.Group}s.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the values and try
* and convert them.
*
* @param groupName the group name
* @return a list of Group, which might be empty but not null
*/
public Collection<? extends Group> getGroupAttributes(String groupName) {
List<Group> retval = new ArrayList<Group>();
for (GoogleBaseAttribute attr: attributes) {
if (hasNameAndType(attr, groupName, GoogleBaseAttributeType.GROUP)) {
retval.add(ConversionUtil.extractGroup(attr));
}
}
return retval;
}
/**
* Gets the first value of a specific attribute, as a
* {@link com.google.api.gbase.client.Shipping}.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the value and try
* and convert it.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted.
*/
public Shipping getShippingAttribute(String name) {
GoogleBaseAttribute value = getAttribute(name);
if (value == null) {
return null;
}
return ConversionUtil.extractShipping(value);
}
/**
* Gets all the values of a specific attribute, as a list of
* {@link com.google.api.gbase.client.Shipping}s.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the values and try
* and convert them.
*
* @param name attribute name
* @return a list of Shipping, which might be empty but not null
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public List<? extends Shipping> getShippingAttributes(String name) {
List<Shipping> retval = new ArrayList<Shipping>();
for (GoogleBaseAttribute attr: attributes) {
if (hasNameAndType(attr, name, GoogleBaseAttributeType.SHIPPING)) {
retval.add(ConversionUtil.extractShipping(attr));
}
}
return retval;
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#SHIPPING}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param shipping attribute value
*/
public void addShippingAttribute(String name, Shipping shipping) {
addAttribute(ConversionUtil.createAttribute(name, shipping));
}
/**
* Gets the first value of a specific attribute, as a
* {@link com.google.api.gbase.client.Tax}.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the value and try
* and convert it.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted.
*/
public Tax getTaxAttribute(String name) {
GoogleBaseAttribute value = getAttribute(name);
if (value == null) {
return null;
}
return ConversionUtil.extractTax(value);
}
/**
* Gets all the values of a specific attribute, as a list of
* {@link com.google.api.gbase.client.Tax}s.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the values and try
* and convert them.
*
* @param name attribute name
* @return a list of Tax, which might be empty but not null
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public List<? extends Tax> getTaxAttributes(String name) {
List<Tax> retval = new ArrayList<Tax>();
for (GoogleBaseAttribute attr: attributes) {
if (hasNameAndType(attr, name, GoogleBaseAttributeType.TAX)) {
retval.add(ConversionUtil.extractTax(attr));
}
}
return retval;
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#TAX}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param tax attribute value
*/
public void addTaxAttribute(String name, Tax tax) {
addAttribute(ConversionUtil.createAttribute(name, tax));
}
/**
* Gets the first value of a specific location attribute, as an
* address.
*
* If you would like to get latitude and longitude and not
* just the address, use {@link #getLocationAttributeAsObject(String)}
* instead.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted.
*/
public String getLocationAttribute(String name) {
return getAttributeAsString(name, GoogleBaseAttributeType.LOCATION);
}
/**
* Gets the first value of a specific location attribute, as a
* location object.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted.
*/
public Location getLocationAttributeAsObject(String name) {
GoogleBaseAttribute attribute = getAttribute(name);
if (attribute == null) {
return null;
}
return ConversionUtil.extractLocation(attribute);
}
/**
* Gets all the values of a specific location attribute, as a list of
* strings.
*
* @param name attribute name
* @return a list of locations, which might be empty but not null
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public List<? extends String> getLocationAttributes(String name) {
return getAttributeValuesAsString(name, GoogleBaseAttributeType.LOCATION);
}
/**
* Gets all the values of a specific attribute, as a list of
* {@link Location} objects.
*
* @param name attribute name
* @return a list of locations, which might be empty but not null
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public List<Location> getLocationAttributesAsObjects(String name) {
List<? extends GoogleBaseAttribute> attributes =
getAttributes(name, GoogleBaseAttributeType.LOCATION);
List<Location> retval = new ArrayList<Location>(attributes.size());
for (GoogleBaseAttribute attribute : attributes) {
retval.add(ConversionUtil.extractLocation(attribute));
}
return retval;
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#LOCATION}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param location attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addLocationAttribute(String name, String location) {
return addAttribute(new GoogleBaseAttribute(name,
GoogleBaseAttributeType.LOCATION, location));
}
/**
* Adds an attribute of type
* {@link com.google.api.gbase.client.GoogleBaseAttributeType#LOCATION}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param location attribute value
* @return the attribute object that has been created and added to the item
*/
public GoogleBaseAttribute addLocationAttribute(String name,
Location location) {
return addAttribute(ConversionUtil.createAttribute(name, location));
}
/**
* Gets the first value of a specific attribute, as a
* {@link com.google.api.gbase.client.DateTimeRange}.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the value and try
* and convert it.
*
* @param name attribute name
* @return value of the attribute or null if no attribute
* with this name was found on the list
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public DateTimeRange getDateTimeRangeAttribute(String name) {
GoogleBaseAttribute value = getAttribute(name);
if (value == null) {
return null;
}
return ConversionUtil.extractDateTimeRange(value);
}
/**
* Gets all the values of a specific attribute, as a list of
* {@link com.google.api.gbase.client.DateTimeRange}.
*
* This method does not check the type of the attribute
* that's being queried, it just gets the values and try
* and convert them.
*
* @param name attribute name
* @return a list of DateTimeRange, which might be empty but not null
* @exception NumberFormatException if some value was
* found that could not be converted
*/
public List<? extends DateTimeRange> getDateTimeRangeAttributes(String name) {
List<DateTimeRange> retval = new ArrayList<DateTimeRange>();
for (GoogleBaseAttribute attr: attributes) {
if (hasNameAndType(attr, name,
GoogleBaseAttributeType.DATE_TIME_RANGE)) {
retval.add(ConversionUtil.extractDateTimeRange(attr));
}
}
return retval;
}
/**
* Adds an attribute of type
* {@link GoogleBaseAttributeType#DATE_TIME_RANGE}.
*
* This method will never remove an attribute, even if it has
* the same name as the new attribute. If you would like to set
* an attribute that can only appear once, call
* {@link #removeAttributes(String, GoogleBaseAttributeType)} first.
*
* @param name attribute name
* @param dateTimeRange attribute value
* @return the attribute object that has been created and added to the item
* @exception IllegalArgumentException if the DateTimeRange is an empty
* range, in which case {@link #addDateTimeAttribute(String,
* com.google.gdata.data.DateTime)} should be used instead.
*/
public GoogleBaseAttribute addDateTimeRangeAttribute(String name,
DateTimeRange dateTimeRange) {
if (dateTimeRange.isDateTimeOnly()) {
// The server would reject such a range
throw new IllegalArgumentException("Empty DateTimeRange. Add " +
"it as a single DateTime using addDateTimeAttribute() instead.");
}
return addAttribute(ConversionUtil.createAttribute(name, dateTimeRange));
}
/**
* Implements
* {@link Extension#generate(XmlWriter, ExtensionProfile)}.
*
* This method generates XML code for the attribute in this extension.
* It is meant to be called by the Google data library.
*
* @param xmlWriter
* @param extensionProfile
*/
public void generate(XmlWriter xmlWriter, ExtensionProfile extensionProfile)
throws IOException {
for (GoogleBaseAttribute attribute : attributes) {
generateAttribute(attribute, xmlWriter);
}
}
private void generateAttribute(GoogleBaseAttribute attribute, XmlWriter xmlWriter)
throws IOException {
String elementName = convertToElementName(attribute.getAttributeId().getName());
xmlWriter.startElement(GoogleBaseNamespaces.G,
elementName,
getXmlAttributes(attribute),
null);
generateValue(attribute, xmlWriter);
generateSubElements(attribute, xmlWriter);
generateAdjustments(attribute, xmlWriter);
generateSubAttributes(attribute, xmlWriter);
xmlWriter.endElement();
}
/**
* Generates XML code for the value of the {@code attribute}.
*
* @param attribute
* @param xmlWriter
* @throws java.io.IOException
*/
private void generateValue(GoogleBaseAttribute attribute, XmlWriter xmlWriter)
throws IOException {
if (attribute.hasValue()) {
xmlWriter.characters(attribute.getValueAsString());
}
}
/**
* Generates XML code for all sub-elements of the {@code attribute}.
*
* @param attribute
* @param xmlWriter
* @throws IOException
*/
private void generateSubElements(GoogleBaseAttribute attribute,
XmlWriter xmlWriter) throws IOException {
if (attribute.hasSubElements()) {
for (String name : attribute.getSubElementNames()) {
for (String element : attribute.getSubElementValues(name)) {
writeXmlNameValue(xmlWriter, GoogleBaseNamespaces.G, name, element);
}
}
}
}
/**
* Generates XML code for all sub-attributes of the {@code attribute}.
*
* @param attribute
* @param xmlWriter
* @throws IOException
*/
private void generateSubAttributes(GoogleBaseAttribute attribute,
XmlWriter xmlWriter) throws IOException {
if (attribute.hasSubAttributes()) {
for (GoogleBaseAttribute element : attribute.getSubAttributes()) {
generateAttribute(element, xmlWriter);
}
}
}
/**
* Generates XML code for the adjustments of the {@code attribute}
* ({@code adjusted_value}, {@code adjusted_name}).
*
* @param attribute
* @param xmlWriter
* @throws IOException
*/
private void generateAdjustments(GoogleBaseAttribute attribute,
XmlWriter xmlWriter) throws IOException {
if (attribute.hasAdjustments()) {
Adjustments adjustments = attribute.getAdjustments();
if (adjustments.getName() != null) {
writeXmlNameValue(xmlWriter, GoogleBaseNamespaces.GM,
GM_ADJUSTED_NAME_ATTRIBUTE, adjustments.getName());
}
if (adjustments.getValue() != null) {
writeXmlNameValue(xmlWriter, GoogleBaseNamespaces.GM,
GM_ADJUSTED_VALUE_ATTRIBUTE, adjustments.getValue());
}
}
}
/**
* Writes a attribute to the {@code xmlWriter} with the specified
* {@code namespace} and {@code name} and with the text content defined by
* the {@code value}.
*
* @param xmlWriter
* @param namespace
* @param name
* @param value
* @throws IOException
*/
private void writeXmlNameValue(XmlWriter xmlWriter, Namespace namespace,
String name, String value) throws IOException {
xmlWriter.startElement(namespace,
convertToElementName(name),
null,
null);
xmlWriter.characters(value);
xmlWriter.endElement();
}
/**
* Converts an attribute name (with space) to an XML
* element name (with underscores).
*
* @param attributeName
* @return corresponding element name
*/
private String convertToElementName(String attributeName) {
return attributeName.replace(' ', '_');
}
/**
* Converts an XML element local name (with underscores) to
* an attribute name (with spaces).
*
* @param localName element name without namespace prefix
* @return corresponding attribute name
*/
private String convertToAttributeName(String localName) {
return localName.replace('_', ' ');
}
/**
* Returns the XML attributes that should be set to the
* element corresponding to the given
* {@link com.google.api.gbase.client.GoogleBaseAttribute}.
*
* This method is meant to be implemented in subclasses that need
* so set attributes. By default, it defines no attributes and
* simply returns null.
*
* @param attribute
* @return a collection of XML attributes or null
*/
private Collection<XmlWriter.Attribute> getXmlAttributes(
GoogleBaseAttribute attribute) {
GoogleBaseAttributeType type = attribute.getAttributeId().getType();
if (type == null) {
return null;
}
List<XmlWriter.Attribute> attributes = new ArrayList<XmlWriter.Attribute>();
attributes.add(new XmlWriter.Attribute("type", type.toString()));
if (attribute.isPrivate()) {
attributes.add(new XmlWriter.Attribute("access", "private"));
}
return attributes;
}
/**
* Given an XML element local name and its attributes, creates
* an {@link com.google.api.gbase.client.GoogleBaseAttribute}.
*
* This method reads the 'type' attribute and set it in the
* {@link GoogleBaseAttribute}.
*
* @param attributeName attribute name, with spaces
* @param xmlAttributes XML attributes for the current element
* @return the GoogleBaseAttribute for the XML tag
*/
private GoogleBaseAttribute createExtensionAttribute(
String attributeName, Attributes xmlAttributes) {
String type = xmlAttributes.getValue("type");
String access = xmlAttributes.getValue("access");
boolean privateAccess = "private".equals(access);
return new GoogleBaseAttribute(attributeName,
GoogleBaseAttributeType.getInstance(type),
privateAccess);
}
/**
* Implements
* {@link Extension#getHandler(ExtensionProfile, String, String, Attributes)}.
*
* This method returns a handler object that can parse an attribute in
* the current namespace and add the corresponding {@link GoogleBaseAttribute}
* into the list.
*
* It is meant to be called by the Google data library.
*/
public XmlParser.ElementHandler getHandler(ExtensionProfile extensionProfile,
String uri, String localName,
Attributes attributes)
throws ParseException, IOException {
return new Handler(localName, attributes);
}
/**
* Gets the application attribute.
*
* This attribute should contain the name of the last application that
* modified the entry. This is informative only and should not be relied
* on.
*
* @return application attribute
*/
public String getApplication() {
return getTextAttribute(APPLICATION_ATTRIBUTE);
}
/**
* Sets the application attribute.
*
* This attribute should be set every time an entry is inserted
* or updated. It is set automatically by
* {@link GoogleBaseService#update(java.net.URL,
* com.google.gdata.data.BaseEntry)}
* {@link GoogleBaseService#insert(java.net.URL,
* com.google.gdata.data.BaseEntry)} and
* {@link GoogleBaseService#batch(java.net.URL,
* com.google.gdata.data.BaseFeed)}.
*
* @param name
*/
public void setApplication(String name) {
removeAttributes(APPLICATION_ATTRIBUTE, GoogleBaseAttributeType.TEXT);
addTextAttribute(APPLICATION_ATTRIBUTE, name);
}
/**
* Private handler for one XML tag that creates and adds
* an {@link com.google.api.gbase.client.GoogleBaseAttribute} into the list.
*
*/
private class Handler extends XmlParser.ElementHandler {
/*
* This handler supposes that all tags in the namespace look like this:
*
* <x:tag_name [type='...']>...text...</x:tag_name>
*
* or like this:
*
* <x:tag_name [type='...']>
* <x:subtag1>...text...</x:subtag1>
* <x:subtag2>...text...</x:subtag2>
* ...
* </x:tag_name> (with all sub tags appearing at most once)
*
* Anything else will be ignored.
*/
private final GoogleBaseAttribute attribute;
Handler(String localName, Attributes xmlAttributes) {
String attributeName = convertToAttributeName(localName);
this.attribute = createExtensionAttribute(attributeName, xmlAttributes);
attributes.add(attribute);
}
@Override
public void processEndElement() throws ParseException {
if (super.value != null) {
attribute.setValue(super.value);
}
}
@Override
public XmlParser.ElementHandler getChildHandler(final String uri,
final String localName,
Attributes attrs) {
GoogleBaseAttributeType type = this.attribute.getType();
if (type != null && GoogleBaseAttributeType.GROUP.isSupertypeOf(type)) {
return new GroupSubAttrHandler(localName, attrs);
}
return new XmlParser.ElementHandler() {
private int width = -1;
private int height = -1;
@Override
public void processEndElement() {
if (GoogleBaseNamespaces.GM_URI.equals(uri)) {
if (GM_ADJUSTED_VALUE_ATTRIBUTE.equals(localName)) {
attribute.getAdjustments().setValue(super.value);
} else if (GM_ADJUSTED_NAME_ATTRIBUTE.equals(localName)) {
attribute.getAdjustments().setName(super.value);
} else if (GM_THUMBNAIL_ATTRIBUTE.equals(localName)) {
Thumbnail thumbnail = new Thumbnail();
thumbnail.setUrl(super.value.trim());
if ((width > 0) && (height > 0)) {
thumbnail.setSize(width, height);
}
attribute.getThumbnails().add(thumbnail);
}
// if the uri is gm but the name is not recognized, we ignore it
} else {
// only non-gm uris are considered sub-elements
attribute.appendSubElement(localName, super.value);
}
}
@Override
public void processAttribute(String namespace, String localName,
String value) throws ParseException {
if ("width".equals(localName)) {
width = parseInteger(value);
} else if ("height".equals(localName)) {
height = parseInteger(value);
}
}
private int parseInteger(String value) throws ParseException {
try {
return Integer.parseInt(value);
} catch (NumberFormatException nfe) {
throw new ParseException(
"Invalid size value '" + value + "'", nfe);
}
}
};
}
}
/**
* Private handler for one XML tag of type "group" and creates and adds
* an {@link com.google.api.gbase.client.GoogleBaseAttribute} into the list.
*/
private class GroupSubAttrHandler extends XmlParser.ElementHandler {
private final GoogleBaseAttribute attribute;
GroupSubAttrHandler(String localName, Attributes xmlAttributes) {
String attributeName = convertToAttributeName(localName);
this.attribute = createExtensionAttribute(attributeName, xmlAttributes);
attributes.get(attributes.size() - 1).addSubAttribute(attribute);
}
@Override
public void processEndElement() {
if (super.value != null) {
attribute.setValue(super.value);
}
}
@Override
public XmlParser.ElementHandler getChildHandler(final String uri,
final String localName,
Attributes attrs) {
return new XmlParser.ElementHandler() {
@Override
public void processEndElement() {
if (GoogleBaseNamespaces.GM_URI.equals(uri)) {
if (GM_ADJUSTED_VALUE_ATTRIBUTE.equals(localName)) {
attribute.getAdjustments().setValue(super.value);
} else if (GM_ADJUSTED_NAME_ATTRIBUTE.equals(localName)) {
attribute.getAdjustments().setName(super.value);
}
// if the uri is gm but the name is not recognized, we ignore it
} else {
// only non-gm uris are considered sub-elements
attribute.appendSubElement(localName, super.value);
}
}
};
}
}
}