/* 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.model.atom;
import com.google.gdata.util.common.base.Preconditions;
import com.google.gdata.data.ICategory;
import com.google.gdata.model.AttributeKey;
import com.google.gdata.model.Element;
import com.google.gdata.model.ElementCreator;
import com.google.gdata.model.ElementKey;
import com.google.gdata.model.ElementMetadata;
import com.google.gdata.model.MetadataRegistry;
import com.google.gdata.model.QName;
import com.google.gdata.model.ValidationContext;
import com.google.gdata.model.ElementMetadata.Cardinality;
import com.google.gdata.util.Namespaces;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* The Category class represents the data model for the Atom category element.
*/
public class Category extends Element implements ICategory {
/**
* The key for this element.
*/
public static final ElementKey<Void, Category> KEY = ElementKey.of(
new QName(Namespaces.atomNs, "category"), Category.class);
/**
* The category scheme attribute.
*/
public static final AttributeKey<String> SCHEME = AttributeKey.of(
new QName("scheme"));
/**
* The category term attribute.
*/
public static final AttributeKey<String> TERM = AttributeKey.of(
new QName("term"));
/**
* The category label attribute.
*/
public static final AttributeKey<String> LABEL = AttributeKey.of(
new QName("label"));
/**
* Qualified name for the XML lang attribute
*/
public static final AttributeKey<String> XML_LANG = AttributeKey.of(
new QName(Namespaces.xmlNs, "lang"));
/**
* Registers the metadata for this element.
*/
public static void registerMetadata(MetadataRegistry registry) {
if (registry.isRegistered(KEY)) {
return;
}
ElementCreator builder = registry.build(KEY)
.setCardinality(Cardinality.SET);
builder.addAttribute(XML_LANG);
builder.addAttribute(SCHEME);
builder.addAttribute(TERM).setRequired(true);
builder.addAttribute(LABEL);
}
/**
* Constructs a new category instance using the default metadata.
*/
public Category() {
super(KEY);
}
/**
* Constructs a new category instance using the specified element key.
*
* @param key the element key for the category.
*/
protected Category(ElementKey<?, ? extends Category> key) {
super(key);
}
/**
* Constructs a new instance by doing a shallow copy of data from an existing
* {@link Element} instance. Will use the given {@link ElementKey} as
* the key for the element.
*
* @param key the element key to use for the category
* @param source source element
*/
protected Category(ElementKey<?, ? extends Category> key, Element source) {
super(key, source);
}
// A simple pattern matcher for the "{scheme}term" syntax
private static final Pattern categoryPattern =
Pattern.compile("(\\{([^\\}]+)\\})?(.+)");
/**
* Constructs a new category from a Category string. The format of
* the String is the same as the one used to represent a category in
* a GData query: an optional scheme surrounded by braces, followed
* by a term.
*
* @param category the category string
*/
public Category(String category) {
this();
Matcher m = categoryPattern.matcher(category);
if (!m.matches()) {
throw new IllegalArgumentException("Invalid category: " + category);
}
if (m.group(2) != null) {
setScheme(m.group(2));
}
setTerm(m.group(3));
}
/**
* Constructs a new category with the specified scheme and term values.
*/
public Category(String scheme, String term) { this(scheme, term, null); }
/**
* Constructs a new category with the specified scheme, term, and label
* values.
*/
public Category(String scheme, String term, String label) {
this();
setScheme(scheme);
if (term == null) {
throw new NullPointerException("Invalid term. Cannot be null");
}
setTerm(term);
setLabel(label);
}
@Override
public Category lock() {
return (Category) super.lock();
}
/**
* Returns the category scheme or {@code null} if the category does not have
* a scheme.
*/
public String getScheme() {
return getAttributeValue(SCHEME);
}
/**
* Sets the category scheme. A value of {@code null} indicates that there is
* no category scheme.
* @param scheme category scheme URI.
*/
public void setScheme(String scheme) {
setAttributeValue(SCHEME, scheme);
}
/**
* Returns the category term.
* @return category term value.
*/
public String getTerm() {
return getAttributeValue(TERM);
}
/**
* Sets the category term value.
* @param term
*/
public void setTerm(String term) {
Preconditions.checkNotNull(term, "Null category term");
setAttributeValue(TERM, term);
}
/**
* Returns the category label or {@code null} if there is no label value.
* @return category label (or @code null}.
*/
public String getLabel() {
return getAttributeValue(LABEL);
}
/**
* Sets the category label. A value of {@code null} indicates that there is
* no label.
* @param label category label value.
*/
public void setLabel(String label) {
setAttributeValue(LABEL, label);
}
/**
* Returns the language associated with the category label (or {@code null}
* if undefined).
*/
public String getLabelLang() {
return getAttributeValue(XML_LANG);
}
/**
* Sets the language associated with the category label (or {@code nulll} if
* undefined).
* @param lang label language.
*/
public void setLabelLang(String lang) {
setAttributeValue(XML_LANG, lang);
}
@Override
protected Element narrow(ElementMetadata<?, ?> meta, ValidationContext vc) {
return adapt(this, meta, getScheme());
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
String scheme = getScheme();
if (scheme != null) {
sb.append("{");
sb.append(scheme);
sb.append("}");
}
// Label syntax is not in the query model, so no need to define
// public constants for the delimiters.
sb.append(getTerm());
String label = getLabel();
if (label != null) {
sb.append("(");
sb.append(label);
sb.append(")");
}
return sb.toString();
}
@Override
public boolean equals(Object obj) {
if (! (obj instanceof Category)) {
return false;
}
Category other = (Category) obj;
String scheme = getScheme();
if (scheme == null) {
if (other.getScheme() != null) {
return false;
}
} else if (!scheme.equals(other.getScheme())) {
return false;
}
String term = getTerm();
if (term == null) {
if (other.getTerm() != null) {
return false;
}
} else if (!term.equals(other.getTerm())) {
return false;
}
String label = getLabel();
if (label == null) {
if (other.getLabel() != null) {
return false;
}
} else if (!label.equals(other.getLabel())) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = 17;
String scheme = getScheme();
result = 37 * result + ((scheme != null) ? scheme.hashCode() : 0);
String term = getTerm();
result = 37 * result + ((term != null) ? term.hashCode() : 0);
String label = getLabel();
result = 37 * result + ((label != null) ? label.hashCode() : 0);
return result;
}
}