/* Copyright (c) 2001 - 2009 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.catalog.rest;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.geoserver.catalog.Catalog;
import org.geoserver.config.util.XStreamPersister;
import org.geoserver.ows.util.OwsUtils;
import org.geoserver.rest.format.ReflectiveJSONFormat;
import org.geoserver.rest.format.ReflectiveXMLFormat;
import org.restlet.Context;
import org.restlet.data.Request;
import org.restlet.data.Response;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public abstract class AbstractCatalogListResource extends CatalogResourceBase {
protected AbstractCatalogListResource(Context context, Request request,
Response response, Class clazz, Catalog catalog) {
super(context, request, response, clazz, catalog);
}
@Override
protected final Object handleObjectGet() throws Exception {
return XStreamPersister.unwrapProxies( handleListGet() );
}
protected abstract Collection handleListGet() throws Exception;
//JD: we create custom formats here because we need to set up the collection aliases
// correctly, basically whatever collection we get back we ant to alias to layers, featureTypes,
// coverages, styles, etc...
@Override
protected ReflectiveJSONFormat createJSONFormat(Request request, Response response) {
final ReflectiveJSONFormat f = super.createJSONFormat(request, response);
return new ReflectiveJSONFormat() {
@Override
public XStream getXStream() {
return f.getXStream();
}
@Override
protected void write(Object data, OutputStream output) throws IOException {
aliasCollection(data, f.getXStream());
f.getXStream().toXML(data, output);
}
};
}
@Override
protected ReflectiveXMLFormat createXMLFormat(Request request, Response response) {
final ReflectiveXMLFormat f = super.createXMLFormat(request, response);
return new ReflectiveXMLFormat() {
@Override
public XStream getXStream() {
return f.getXStream();
}
@Override
protected void write(Object data, OutputStream output) throws IOException {
aliasCollection(data, f.getXStream());
f.getXStream().toXML(data, output);
}
};
}
@Override
protected void configureXStream(XStream xstream) {
XStreamPersister xp = xpf.createXMLPersister();
final String name = xp.getClassAliasingMapper().serializedClass( clazz );
xstream.alias( name, clazz );
xstream.registerConverter(
new CollectionConverter(xstream.getMapper()) {
public boolean canConvert(Class type) {
return Collection.class.isAssignableFrom(type);
};
@Override
protected void writeItem(Object item,
MarshallingContext context,
HierarchicalStreamWriter writer) {
writer.startNode( name );
context.convertAnother( item );
writer.endNode();
}
}
);
xstream.registerConverter(
new Converter() {
public boolean canConvert(Class type) {
return clazz.isAssignableFrom( type );
}
public void marshal(Object source,
HierarchicalStreamWriter writer,
MarshallingContext context) {
String ref = null;
if ( OwsUtils.getter( clazz, "name", String.class ) != null ) {
ref = (String) OwsUtils.get( source, "name");
}
else if ( OwsUtils.getter( clazz, "id", String.class ) != null ) {
ref = (String) OwsUtils.get( source, "id");
}
else {
throw new RuntimeException( "Could not determine identifier for: " + clazz.getName());
}
writer.startNode( "name" );
writer.setValue(ref);
writer.endNode();
encodeLink(encode(ref), writer);
}
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
return null;
}
}
);
}
/**
* Template method to alias the type of the collection.
* <p>
* The default works with list, subclasses may override for instance
* to work with a Set.
* </p>
*/
protected void aliasCollection( Object data, XStream xstream ) {
XStreamPersister xp = xpf.createXMLPersister();
final String alias = xp.getClassAliasingMapper().serializedClass( clazz );
xstream.alias(alias + "s", Collection.class, data.getClass());
}
}