Java tutorial
/** * Copyright (C) 2009-2012 Couchbase, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING * IN THE SOFTWARE. */ package com.couchbase.spring.core.convert; import com.couchbase.spring.core.mapping.ConvertedCouchbaseDocument; import com.couchbase.spring.core.mapping.CouchbasePersistentEntity; import com.couchbase.spring.core.mapping.CouchbasePersistentProperty; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.ObjectMapper; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.convert.support.ConversionServiceFactory; import org.springframework.data.convert.EntityInstantiator; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.BeanWrapper; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.ParameterValueProvider; import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider; import org.springframework.data.mapping.model.PropertyValueProvider; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.TypeInformation; import org.springframework.data.mapping.PropertyHandler; import org.springframework.util.Assert; public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implements ApplicationContextAware { protected ApplicationContext applicationContext; protected final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext; protected boolean useFieldAccessOnly = true; @SuppressWarnings("deprecation") public MappingCouchbaseConverter( MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext) { super(ConversionServiceFactory.createDefaultConversionService()); this.mappingContext = mappingContext; } @Override public MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> getMappingContext() { return mappingContext; } private ParameterValueProvider<CouchbasePersistentProperty> getParameterProvider( CouchbasePersistentEntity<?> entity, ConvertedCouchbaseDocument source, Object parent) { CouchbasePropertyValueProvider provider = new CouchbasePropertyValueProvider(source, parent); PersistentEntityParameterValueProvider<CouchbasePersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<CouchbasePersistentProperty>( entity, provider, parent); return parameterProvider; } @Override public <R> R read(Class<R> type, ConvertedCouchbaseDocument doc) { return read(type, doc, null); } public <R> R read(Class<R> type, final ConvertedCouchbaseDocument doc, Object parent) { final CouchbasePersistentEntity<R> entity = (CouchbasePersistentEntity<R>) mappingContext .getPersistentEntity(type); ParameterValueProvider<CouchbasePersistentProperty> provider = getParameterProvider(entity, doc, parent); EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity); R instance = instantiator.createInstance(entity, provider); final BeanWrapper<CouchbasePersistentEntity<R>, R> wrapper = BeanWrapper.create(instance, conversionService); final R result = wrapper.getBean(); // Set properties not already set in the constructor entity.doWithProperties(new PropertyHandler<CouchbasePersistentProperty>() { public void doWithPersistentProperty(CouchbasePersistentProperty prop) { boolean isConstructorProperty = entity.isConstructorArgument(prop); boolean hasValueForProperty = doc.containsField(prop.getFieldName()); if (!hasValueForProperty || isConstructorProperty) { return; } Object obj = null; if (prop.isIdProperty()) { obj = doc.getId(); } else { obj = doc.get(prop.getFieldName()); } wrapper.setProperty(prop, obj, useFieldAccessOnly); } }); return result; } @Override public void write(Object source, ConvertedCouchbaseDocument target) { if (source == null) { return; } TypeInformation<? extends Object> type = ClassTypeInformation.from(source.getClass()); try { writeInternal(source, target, type); } catch (IOException ex) { throw new MappingException( "Could not translate to JSON while converting " + source.getClass().getName()); } } protected void writeInternal(final Object source, ConvertedCouchbaseDocument target, TypeInformation<?> type) throws IOException { CouchbasePersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass()); if (entity == null) { throw new MappingException( "No mapping metadata found for entity of type " + source.getClass().getName()); } final CouchbasePersistentProperty idProperty = entity.getIdProperty(); if (idProperty == null) { throw new MappingException("ID property required for entity of type " + source.getClass().getName()); } final BeanWrapper<CouchbasePersistentEntity<Object>, Object> wrapper = BeanWrapper.create(source, conversionService); String id = wrapper.getProperty(idProperty, String.class, false); target.setId(id); target.setExpiry(entity.getExpiry()); JsonFactory jsonFactory = new JsonFactory(); OutputStream jsonStream = new ByteArrayOutputStream(); final JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(jsonStream, JsonEncoding.UTF8); jsonGenerator.setCodec(new ObjectMapper()); jsonGenerator.writeStartObject(); entity.doWithProperties(new PropertyHandler<CouchbasePersistentProperty>() { @Override public void doWithPersistentProperty(CouchbasePersistentProperty prop) { if (prop.equals(idProperty)) { return; } Object propertyValue = wrapper.getProperty(prop, prop.getType(), false); if (propertyValue != null) { try { jsonGenerator.writeFieldName(prop.getFieldName()); jsonGenerator.writeObject(propertyValue); } catch (IOException ex) { throw new MappingException( "Could not translate to JSON while converting " + source.getClass().getName()); } } } }); jsonGenerator.writeEndObject(); jsonGenerator.close(); target.setRawValue(jsonStream.toString()); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } private class CouchbasePropertyValueProvider implements PropertyValueProvider<CouchbasePersistentProperty> { private final ConvertedCouchbaseDocument source; private final Object parent; public CouchbasePropertyValueProvider(ConvertedCouchbaseDocument source, Object parent) { Assert.notNull(source); this.source = source; this.parent = parent; } public <T> T getPropertyValue(CouchbasePersistentProperty property) { T value = null; if (property.isIdProperty()) { value = (T) source.getId(); } else { value = (T) source.get(property.getFieldName()); } if (value == null) { return null; } return value; } } }