/* 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.introspection;
import com.google.gdata.util.common.xml.XmlNamespace;
import com.google.gdata.util.common.xml.XmlWriter;
import com.google.gdata.util.common.xml.XmlWriter.Attribute;
import com.google.gdata.client.CoreErrorDomain;
import com.google.gdata.client.Service;
import com.google.gdata.data.AttributeHelper;
import com.google.gdata.data.ExtensionPoint;
import com.google.gdata.data.ExtensionProfile;
import com.google.gdata.data.ExtensionVisitor;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.TextConstruct;
import com.google.gdata.util.Namespaces;
import com.google.gdata.util.ParseException;
import com.google.gdata.util.Version;
import com.google.gdata.util.XmlParser;
import org.xml.sax.Attributes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* The Workspace class defines the basic Java object model
* representation and XML parsing/generation support for an
* AtomPub workspace.
*
* The implementation is versioned to support the AtomPub draft version 9
* introspection format (used for the GData v1 implementation) as well
* as the final RFC5023 format (used for all other versions). The key
* difference between the two is that draft used an attribute for the
* workspace title where the final version uses an atom:title element.
* elements.
*
*
*/
public class Workspace extends ExtensionPoint implements IWorkspace {
// Locally case version-dependent information. The assumption here is that
// a single instance isn't used with multiple version of the protocol.
private Version coreVersion = Service.getVersion();
private XmlNamespace atomPubNs = Namespaces.getAtomPubNs();
public Workspace() {}
public Workspace(TextConstruct title) {
this.title = title;
}
/** Title of workspace */
private TextConstruct title;
public TextConstruct getTitle() { return title; }
public void setTitle(TextConstruct v) { title = v; }
/** The list of collections associated with the workspace */
private List<Collection> collectionList = new ArrayList<Collection>();
public List<Collection> getCollections() { return collectionList; }
public void addCollection(Collection coll) { collectionList.add(coll); }
public Collection addCollection(String collectionUri, String title,
String... acceptedTypes) {
Collection collection = new Collection(collectionUri,
new PlainTextConstruct(title), acceptedTypes);
addCollection(collection);
return collection;
}
@Override
protected void visitChildren(ExtensionVisitor ev)
throws ExtensionVisitor.StoppedException {
// Add nested collections to the visitor pattern
for (Collection collection : collectionList) {
this.visitChild(ev, collection);
}
super.visitChildren(ev);
}
@Override
public void generate(XmlWriter w, ExtensionProfile extProfile)
throws IOException {
ArrayList<Attribute> attrs = new ArrayList<Attribute>();
if (coreVersion.isCompatible(Service.Versions.V1)) {
attrs.add(new Attribute("title", title.getPlainText()));
}
w.startElement(atomPubNs, "workspace", attrs, null);
if (!coreVersion.isCompatible(Service.Versions.V1)) {
title.generateAtom(w, "title");
}
w.startRepeatingElement();
for (Collection collection : collectionList) {
collection.generate(w, extProfile);
}
w.endRepeatingElement();
generateExtensions(w, extProfile);
w.endElement(atomPubNs, "workspace");
}
@Override
public void consumeAttributes(AttributeHelper attrHelper)
throws ParseException {
if (coreVersion.isCompatible(Service.Versions.V1)) {
String titleAttr = attrHelper.consume("title", true);
title = new PlainTextConstruct(titleAttr);
}
}
@Override
public XmlParser.ElementHandler getHandler(ExtensionProfile p,
String namespace, String localName, Attributes attrs) {
return new Handler(p, attrs);
}
/**
* XmlParser ElementHandler for {@code app:workspace}
*/
public class Handler extends ExtensionPoint.ExtensionHandler {
public Handler(ExtensionProfile extProfile, Attributes attrs) {
super(extProfile, Workspace.class, attrs);
}
@Override
public XmlParser.ElementHandler getChildHandler(String namespace,
String localName,
Attributes attrs)
throws ParseException, IOException {
if (namespace.equals(atomPubNs.getUri())) {
if (localName.equals("collection")) {
Collection collection = new Collection();
addCollection(collection);
return collection.new Handler(extProfile, attrs);
}
} else if (namespace.equals(Namespaces.atom)) {
if (localName.equals("title") &&
!coreVersion.isCompatible(Service.Versions.V1)) {
if (title != null) {
throw new ParseException(
CoreErrorDomain.ERR.duplicateTitle);
}
TextConstruct.ChildHandlerInfo chi =
TextConstruct.getChildHandler(attrs);
title = chi.textConstruct;
return chi.handler;
}
}
return super.getChildHandler(namespace, localName, attrs);
}
}
public void processEndElement() throws ParseException {
if (title == null) {
throw new ParseException(
CoreErrorDomain.ERR.workspaceTitleRequired);
}
}
}