/**
* Copyright 2005-2011 Noelios Technologies.
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL 1.0 (the
* "Licenses"). You can select the license that you prefer but you may not use
* this file except in compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.opensource.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.opensource.org/licenses/lgpl-2.1.php
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.opensource.org/licenses/cddl1.php
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.com/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/
package org.restlet.ext.jackson;
import java.io.IOException;
import java.io.Writer;
import java.util.logging.Level;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator.Feature;
import org.codehaus.jackson.map.ObjectMapper;
import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
import org.restlet.representation.WriterRepresentation;
/**
* Representation based on the Jackson library. It can serialize and deserialize
* automatically in JSON.
*
* @see <a href="http://jackson.codehaus.org/">Jackson project</a>
* @author Jerome Louvel
* @param <T>
* The type to wrap.
*/
public class JacksonRepresentation<T> extends WriterRepresentation {
/** The (parsed) object to format. */
private T object;
/** The object class to instantiate. */
private Class<T> objectClass;
/** The JSON representation to parse. */
private Representation jsonRepresentation;
/** The modifiable Jackson object mapper. */
private ObjectMapper objectMapper;
/**
* Constructor.
*
* @param mediaType
* The target media type.
* @param object
* The object to format.
*/
@SuppressWarnings("unchecked")
public JacksonRepresentation(MediaType mediaType, T object) {
super(mediaType);
this.object = object;
this.objectClass = (Class<T>) ((object == null) ? null : object
.getClass());
this.jsonRepresentation = null;
this.objectMapper = null;
}
/**
* Constructor.
*
* @param representation
* The representation to parse.
*/
public JacksonRepresentation(Representation representation,
Class<T> objectClass) {
super(representation.getMediaType());
this.object = null;
this.objectClass = objectClass;
this.jsonRepresentation = representation;
this.objectMapper = null;
}
/**
* Constructor.
*
* @param object
* The object to format.
*/
public JacksonRepresentation(T object) {
this(MediaType.APPLICATION_JSON, object);
}
/**
* Creates a Jackson object mapper based on a media type. By default, it
* calls {@link ObjectMapper#ObjectMapper()}.
*
* @return The Jackson object mapper.
*/
protected ObjectMapper createObjectMapper() {
JsonFactory jsonFactory = new JsonFactory();
jsonFactory.configure(Feature.AUTO_CLOSE_TARGET, false);
return new ObjectMapper(jsonFactory);
}
/**
* Returns the wrapped object, deserializing the representation with Jackson
* if necessary.
*
* @return The wrapped object.
*/
public T getObject() {
T result = null;
if (this.object != null) {
result = this.object;
} else if (this.jsonRepresentation != null) {
try {
result = getObjectMapper().readValue(
this.jsonRepresentation.getStream(), this.objectClass);
} catch (IOException e) {
Context.getCurrentLogger().log(Level.WARNING,
"Unable to parse the object with Jackson.", e);
}
}
return result;
}
/**
* Returns the object class to instantiate.
*
* @return The object class to instantiate.
*/
public Class<T> getObjectClass() {
return objectClass;
}
/**
* Returns the modifiable Jackson object mapper. Useful to customize
* mappings.
*
* @return The modifiable Jackson object mapper.
*/
public ObjectMapper getObjectMapper() {
if (this.objectMapper == null) {
this.objectMapper = createObjectMapper();
}
return this.objectMapper;
}
/**
* Sets the object to format.
*
* @param object
* The object to format.
*/
public void setObject(T object) {
this.object = object;
}
/**
*Sets the object class to instantiate.
*
* @param objectClass
* The object class to instantiate.
*/
public void setObjectClass(Class<T> objectClass) {
this.objectClass = objectClass;
}
/**
* Sets the Jackson object mapper.
*
* @param objectMapper
* The Jackson object mapper.
*/
public void setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public void write(Writer writer) throws IOException {
if (jsonRepresentation != null) {
jsonRepresentation.write(writer);
} else if (object != null) {
getObjectMapper().writeValue(writer, object);
}
}
}