001/* 002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.ecm.automation.io.services.codec; 020 021import java.io.IOException; 022import java.lang.reflect.ParameterizedType; 023import java.lang.reflect.Type; 024 025import org.nuxeo.ecm.core.api.CoreSession; 026 027import com.fasterxml.jackson.core.JsonGenerator; 028import com.fasterxml.jackson.core.JsonParser; 029import com.fasterxml.jackson.databind.ObjectMapper; 030 031/** 032 * @author <a href="mailto:[email protected]">Bogdan Stefanescu</a> 033 */ 034public abstract class ObjectCodec<T> { 035 036 public static Class<?> findParametrizedType(Class<?> clazz) { 037 Type superclass = clazz.getGenericSuperclass(); 038 while (superclass instanceof Class<?>) { 039 superclass = ((Class<?>) superclass).getGenericSuperclass(); 040 } 041 if (superclass == null) { 042 throw new RuntimeException("Missing type parameter."); 043 } 044 Type type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; 045 if (!(type instanceof Class<?>)) { 046 throw new RuntimeException("Invalid class parameter type. " + type); 047 } 048 return (Class<?>) type; 049 } 050 051 protected Class<T> type; 052 053 @SuppressWarnings("unchecked") 054 public ObjectCodec() { 055 this.type = (Class<T>) findParametrizedType(getClass()); 056 } 057 058 public ObjectCodec(Class<T> type) { 059 this.type = type; 060 } 061 062 /** 063 * Get this codec type. Implementors can override to return a short name. The default name is the object type name. 064 * 065 * @return 066 */ 067 public String getType() { 068 return type.getName(); 069 } 070 071 /** 072 * Whether this codec is a builtin codec 073 * 074 * @return 075 */ 076 public boolean isBuiltin() { 077 return false; 078 } 079 080 public Class<T> getJavaType() { 081 return type; 082 } 083 084 public void write(JsonGenerator jg, T value) throws IOException { 085 if (jg.getCodec() == null) { 086 jg.setCodec(new ObjectMapper()); 087 } 088 jg.writeObject(value); 089 } 090 091 /** 092 * When the object codec is called the stream is positioned on the first value. For inlined objects this is the 093 * first value after the "entity-type" property. For non inlined objects this will be the object itself (i.e. '{' or 094 * '[') 095 * 096 * @param jp 097 * @return 098 * @throws IOException 099 */ 100 public T read(JsonParser jp, CoreSession session) throws IOException { 101 if (jp.getCodec() == null) { 102 jp.setCodec(new ObjectMapper()); 103 } 104 return jp.readValueAs(type); 105 } 106 107}