/* 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.common.collect.HashMultimap; import com.google.common.collect.Multimap; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Collections; /** * An internal representation for a tag in the g: namespace. */ public class GoogleBaseAttribute { /** Attribute name (with spaces) and type. */ private final GoogleBaseAttributeId attributeId; /** Content of the tag, as text or null for complex tags. */ private String textValue; /** Tag sub-elements (element name, element value) if there are any. */ private Multimap<String, String> subElements; /** Sub-attributes if there are any. */ private List<GoogleBaseAttribute> subAttributes; /** Corresponds to the XML attribute {@code access="private"}. */ private boolean privateAccess; /** * Corresponds to the XML attributes {@code gm:adjusted_name} and * {@code gm:adjusted_value}, or null if none of these tags is specified. */ private Adjustments adjustments; private List<Thumbnail> thumbnails; /** * Creates a new GoogleBaseAttribute with a name and no type. * * @param name */ public GoogleBaseAttribute(String name) { this(new GoogleBaseAttributeId(name, null), null); } /** * Creates a new GoogleBaseAttribute with a name and type. * * @param name * @param type attribute type, one of the TYPE_* defined in this class, * or null */ public GoogleBaseAttribute(String name, GoogleBaseAttributeType type) { this(name, type, null); } /** * Creates a new Extension attribute with a name, type and string content. * * @param name * @param type type attribute type, one of the types defined in * {@link GoogleBaseAttributeType}, some new type or null * @param textValue content of the attribute, as a string * @exception NullPointerException if argument name is null */ public GoogleBaseAttribute(String name, GoogleBaseAttributeType type, String textValue) { this(new GoogleBaseAttributeId(name, type), textValue); } /** * Creates a new GoogleBaseAttribute with a name and type. * * @param name * @param type attribute type, one of the TYPE_* defined in this class, * or null * @param privateAccess if this attributeId is private */ public GoogleBaseAttribute(String name, GoogleBaseAttributeType type, boolean privateAccess) { this(name, type, privateAccess, null); } /** * Creates a new Extension attribute with a name, type and string content. * * @param name * @param type type attribute type, one of the types defined in * {@link GoogleBaseAttributeType}, some new type or null * @param privateAccess if this attribute is private * @param textValue content of the attribute, as a string * @exception NullPointerException if argument name is null */ public GoogleBaseAttribute(String name, GoogleBaseAttributeType type, boolean privateAccess, String textValue) { this(new GoogleBaseAttributeId(name, type), textValue); setPrivate(privateAccess); } /** * Creates a new Extension attribute with an {@link GoogleBaseAttributeId} and * string content. * * @param attributeId attribute name and type * @param textValue content of the attribute, as a string * @exception NullPointerException if argument name is null */ public GoogleBaseAttribute(GoogleBaseAttributeId attributeId, String textValue) { this.attributeId = attributeId; this.textValue = textValue; } /** * Generates a string representation of this attribute. * * The output of this method is in no particular format. * @return a string representation */ @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("["); buf.append(attributeId); buf.append(": "); if (hasValue()) { buf.append(textValue); } if (hasSubElements()) { buf.append(subElements.toString()); } if (hasSubAttributes()) { buf.append(subAttributes.toString()); } buf.append("]"); return buf.toString(); } /** Gets the attribute name. */ public String getName() { return attributeId.getName(); } /** Gets the type of the attribute, or null. */ public GoogleBaseAttributeType getType() { return attributeId.getType(); } /** * Returns the attribute identity, name and type. * * @return attribute name and type */ public GoogleBaseAttributeId getAttributeId() { return attributeId; } /** Gets the attribute value, as a string (or null). */ public String getValueAsString() { return textValue; } /** * Checks whether the attribute should only be shown to the owner of * this item. */ public boolean isPrivate() { return privateAccess; } /** * Declares the attribute as being private or public (the default). * * @param privateAccess */ public void setPrivate(boolean privateAccess) { this.privateAccess = privateAccess; } /** * Sets the attribute value, as a string. * * @param value attribute value */ public void setValue(String value) { this.textValue = value; } /** Returns true if the attribute has some text content. */ public boolean hasValue() { return textValue != null; } /** Returns true if the attribute has sub-tags. */ public boolean hasSubElements() { return subElements != null && !subElements.isEmpty(); } /** * Sets the value of a sub-tag. * * @param name tag name * @param value tag content, as a string or null to remove * the sub-element */ public void setSubElement(String name, String value) { removeSubElement(name); if (subElements == null) { subElements = HashMultimap.create(); } subElements.put(name, value); } /** * Appends the value to a sub-tag value list. If the sub-tag doesn't exist, it * will be created first. If the value is null, the method will do nothing. * * @param name tag name * @param value tag content to be appended. */ public void appendSubElement(String name, String value) { if (value != null) { if (subElements == null) { subElements = HashMultimap.create(); } subElements.put(name, value); } } /** * Gets a value of a sub-tag. * * @param name tag name * @return sub-tag text content or null */ public String getSubElementValue(String name) { if (subElements != null) { Collection<String> elements = subElements.get(name); if (! elements.isEmpty()) { return elements.iterator().next(); } } return null; } /** * Gets all values correspond to the sub-tag. * * @param name name * @return A collection of text content corresponds to the sub-tag (can be empty) */ public Collection<String> getSubElementValues(String name) { if (subElements == null) { return Collections.<String>emptySet(); } return subElements.get(name); } /** * Checks whether a specific sub-element exists. * * @param name element name * @return true if the sub-element exists */ public boolean hasSubElement(String name) { if (subElements == null) { return false; } return subElements.containsKey(name); } /** * Removes a sub-element. * * @param name element names */ public void removeSubElement(String name) { if (subElements != null) { subElements.removeAll(name); } } /** * Gets the name of all sub-elements in this attribute. * * @return a collection of element names, which might * be empty but not null */ public Collection<? extends String> getSubElementNames() { if (subElements == null) { return Collections.emptyList(); } return subElements.keySet(); } /** Returns true if the attribute has sub-attributes. */ public boolean hasSubAttributes() { return subAttributes != null && !subAttributes.isEmpty(); } /** * Gets all sub-attributes. * * @return A list of all sub-attributes (can be empty but not null). */ public List<GoogleBaseAttribute> getSubAttributes() { if (subAttributes == null) { subAttributes = new ArrayList<GoogleBaseAttribute>(); } return subAttributes; } /** * Appends the value to the subAttribute list. */ public void addSubAttribute(GoogleBaseAttribute value) { getSubAttributes().add(value); } public boolean hasAdjustments() { return adjustments != null && !adjustments.isEmpty(); } /** * Gets the adjustments for this attribute. If no adjustments are present, * an empty {@link Adjustments} object is created, linked to this attribute * and returned. * * @return the adjustments for this attribute. */ public Adjustments getAdjustments() { if (adjustments == null) { adjustments = new Adjustments(); } return adjustments; } /** * Returns true if the attribute has thumbnails, false otherwise. */ public boolean hasThumbnails() { return thumbnails != null && thumbnails.size() > 0; } /** * Gets the reference to the list of thumbnails for this attribute. The result * might be empty, but never null. */ public List<Thumbnail> getThumbnails() { if (thumbnails == null) { thumbnails = new ArrayList<Thumbnail>(); } return thumbnails; } @Override public int hashCode() { int retval = 27 + attributeId.hashCode(); if (textValue != null) { retval += 49 * textValue.hashCode(); } if (subElements != null) { retval += subElements.hashCode(); } return retval; } @Override public boolean equals(Object o) { if (o == null || !(o instanceof GoogleBaseAttribute)) { return false; } GoogleBaseAttribute other = (GoogleBaseAttribute)o; return attributeId.equals(other.attributeId) && privateAccess == other.privateAccess && equalsMaybeNull(textValue, other.textValue) && equalsMaybeNull(subElements, other.subElements); } private static boolean equalsMaybeNull(Object a, Object b) { if (a == null) { return b == null; } return a.equals(b); } }