diff --git a/pom.xml b/pom.xml index 940ad405..22fa28c0 100644 --- a/pom.xml +++ b/pom.xml @@ -72,5 +72,10 @@ spring-data-commons-core 1.4.0.RELEASE + + org.codehaus.jackson + jackson-core-asl + 1.9.11 + diff --git a/src/main/java/com/couchbase/spring/cache/CouchbaseCache.java b/src/main/java/com/couchbase/spring/cache/CouchbaseCache.java index adc0b9fb..1be3be41 100644 --- a/src/main/java/com/couchbase/spring/cache/CouchbaseCache.java +++ b/src/main/java/com/couchbase/spring/cache/CouchbaseCache.java @@ -27,8 +27,8 @@ import org.springframework.cache.Cache; import org.springframework.cache.support.SimpleValueWrapper; /** - * The CouchbaseCache class implements the common cache operations on top of - * a CouchbaseClient instance. + * The CouchbaseCache class implements the Spring Cache interface + * on top of Couchbase Server and the Couchbase Java SDK. */ public class CouchbaseCache implements Cache { diff --git a/src/main/java/com/couchbase/spring/cache/CouchbaseCacheManager.java b/src/main/java/com/couchbase/spring/cache/CouchbaseCacheManager.java index 42ff2f2e..213c71ea 100644 --- a/src/main/java/com/couchbase/spring/cache/CouchbaseCacheManager.java +++ b/src/main/java/com/couchbase/spring/cache/CouchbaseCacheManager.java @@ -31,8 +31,11 @@ import org.springframework.cache.Cache; import org.springframework.cache.support.AbstractCacheManager; /** - * The CouchbaseCacheManager handles CouchbaseClient connections and - * orchestrates them as needed. + * The CouchbaseCacheManager orchestrates CouchbaseCache instances. + * + * Since more than one current CouchbaseClient connection can be used + * for caching, the CouchbaseCacheManager orchestrates and handles + * them for the Spring Cache abstraction layer. */ public class CouchbaseCacheManager extends AbstractCacheManager { diff --git a/src/main/java/com/couchbase/spring/config/AbstractCouchbaseConfiguration.java b/src/main/java/com/couchbase/spring/config/AbstractCouchbaseConfiguration.java new file mode 100644 index 00000000..fa1b21f7 --- /dev/null +++ b/src/main/java/com/couchbase/spring/config/AbstractCouchbaseConfiguration.java @@ -0,0 +1,121 @@ +/** + * 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.config; + +import com.couchbase.client.CouchbaseClient; +import com.couchbase.spring.core.CouchbaseMappingContext; +import com.couchbase.spring.core.CouchbaseTemplate; +import com.couchbase.spring.core.convert.MappingCouchbaseConverter; +import com.couchbase.spring.core.mapping.Document; +import java.util.HashSet; +import java.util.Set; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.data.annotation.Persistent; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +/** + * Base class for Spring Data Couchbase configuration using JavaConfig. + */ +@Configuration +public abstract class AbstractCouchbaseConfiguration { + + /** + * Return the {@link CouchbaseClient} instance to connect to. + */ + @Bean + public abstract CouchbaseClient couchbaseClient() throws Exception; + + /** + * Creates a {@link CouchbaseTemplate}. + */ + @Bean + public CouchbaseTemplate couchbaseTemplate() throws Exception { + return new CouchbaseTemplate(couchbaseClient(), mappingCouchbaseConverter()); + } + + /** + * Creates a {@link MappingCouchbaseConverter} using the configured {@link + * #couchbaseMappingContext}. + */ + @Bean + public MappingCouchbaseConverter mappingCouchbaseConverter() throws Exception { + return new MappingCouchbaseConverter(couchbaseMappingContext()); + } + + /** + * Creates a {@link CouchbaseMappingContext} equipped with entity classes + * scanned from the mapping base package. + */ + @Bean + public CouchbaseMappingContext couchbaseMappingContext() throws Exception { + CouchbaseMappingContext mappingContext = new CouchbaseMappingContext(); + mappingContext.setInitialEntitySet(getInitialEntitySet()); + return mappingContext; + } + + /** + * Scans the mapping base package for classes annotated with {@link Document}. + */ + protected Set> getInitialEntitySet() throws ClassNotFoundException { + String basePackage = getMappingBasePackage(); + Set> initialEntitySet = new HashSet>(); + + if(StringUtils.hasText(basePackage)) { + ClassPathScanningCandidateComponentProvider componentProvider = + new ClassPathScanningCandidateComponentProvider(false); + componentProvider.addIncludeFilter( + new AnnotationTypeFilter(Document.class)); + componentProvider.addIncludeFilter( + new AnnotationTypeFilter(Persistent.class)); + + for (BeanDefinition candidate : + componentProvider.findCandidateComponents(basePackage)) { + initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(), + AbstractCouchbaseConfiguration.class.getClassLoader())); + } + } + + return initialEntitySet; + } + + /** + * Return the base package to scan for mapped {@link Document}s. Will return + * the package name of the configuration class (the concrete class, not this + * one here) by default. So if you have a {@code com.acme.AppConfig} extending + * {@link AbstractCouchbaseConfiguration} the base package will be considered + * {@code com.acme} unless the method is overridden to implement alternate + * behavior. + * + * @return the base package to scan for mapped {@link Document} classes or + * {@literal null} to not enable scanning for entities. + */ + protected String getMappingBasePackage() { + return getClass().getPackage().getName(); + } + +} diff --git a/src/main/java/com/couchbase/spring/core/CouchbaseMappingContext.java b/src/main/java/com/couchbase/spring/core/CouchbaseMappingContext.java new file mode 100644 index 00000000..c1740f7e --- /dev/null +++ b/src/main/java/com/couchbase/spring/core/CouchbaseMappingContext.java @@ -0,0 +1,64 @@ +/** + * 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; + +import com.couchbase.spring.core.mapping.BasicCouchbasePersistentEntity; +import com.couchbase.spring.core.mapping.BasicCouchbasePersistentProperty; +import com.couchbase.spring.core.mapping.CouchbasePersistentProperty; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.data.mapping.context.AbstractMappingContext; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.TypeInformation; + +public class CouchbaseMappingContext + extends AbstractMappingContext, CouchbasePersistentProperty> + implements ApplicationContextAware { + + private ApplicationContext context; + + @Override + protected BasicCouchbasePersistentEntity createPersistentEntity(TypeInformation typeInformation) { + BasicCouchbasePersistentEntity entity = new BasicCouchbasePersistentEntity(typeInformation); + if(context != null) { + entity.setApplicationContext(context); + } + return entity; + } + + @Override + protected CouchbasePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, BasicCouchbasePersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { + return new BasicCouchbasePersistentProperty(field, descriptor, owner, simpleTypeHolder); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.context = applicationContext; + super.setApplicationContext(applicationContext); + } + +} diff --git a/src/main/java/com/couchbase/spring/core/CouchbaseOperations.java b/src/main/java/com/couchbase/spring/core/CouchbaseOperations.java new file mode 100644 index 00000000..c6641118 --- /dev/null +++ b/src/main/java/com/couchbase/spring/core/CouchbaseOperations.java @@ -0,0 +1,27 @@ +/** + * 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; + +public interface CouchbaseOperations { + +} diff --git a/src/main/java/com/couchbase/spring/core/CouchbaseTemplate.java b/src/main/java/com/couchbase/spring/core/CouchbaseTemplate.java new file mode 100644 index 00000000..59fbd176 --- /dev/null +++ b/src/main/java/com/couchbase/spring/core/CouchbaseTemplate.java @@ -0,0 +1,51 @@ +/** + * 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; + +import com.couchbase.client.CouchbaseClient; +import com.couchbase.spring.core.convert.CouchbaseConverter; +import com.couchbase.spring.core.convert.MappingCouchbaseConverter; + +public class CouchbaseTemplate implements CouchbaseOperations { + + private CouchbaseClient client; + private CouchbaseConverter couchbaseConverter; + + public CouchbaseTemplate(CouchbaseClient client) { + this(client, null); + } + + public CouchbaseTemplate(CouchbaseClient client, CouchbaseConverter converter) { + this.client = client; + this.couchbaseConverter = converter == null ? getDefaultConverter(client) : converter; + } + + private CouchbaseConverter getDefaultConverter(CouchbaseClient client) { + MappingCouchbaseConverter converter = new MappingCouchbaseConverter( + new CouchbaseMappingContext()); + converter.afterPropertiesSet(); + return converter; + } + + +} diff --git a/src/main/java/com/couchbase/spring/core/convert/AbstractCouchbaseConverter.java b/src/main/java/com/couchbase/spring/core/convert/AbstractCouchbaseConverter.java index fbe325e1..cf54d9ff 100644 --- a/src/main/java/com/couchbase/spring/core/convert/AbstractCouchbaseConverter.java +++ b/src/main/java/com/couchbase/spring/core/convert/AbstractCouchbaseConverter.java @@ -40,7 +40,8 @@ public abstract class AbstractCouchbaseConverter implements CouchbaseConverter, return conversionService; } - public void afterPropertiesSet() throws Exception { + @Override + public void afterPropertiesSet() { } diff --git a/src/main/java/com/couchbase/spring/core/convert/MappingCouchbaseConverter.java b/src/main/java/com/couchbase/spring/core/convert/MappingCouchbaseConverter.java index 786c069d..0fed7fb4 100644 --- a/src/main/java/com/couchbase/spring/core/convert/MappingCouchbaseConverter.java +++ b/src/main/java/com/couchbase/spring/core/convert/MappingCouchbaseConverter.java @@ -30,6 +30,8 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.convert.support.ConversionServiceFactory; import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implements ApplicationContextAware { @@ -39,27 +41,39 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter CouchbasePersistentProperty> mappingContext; @SuppressWarnings("deprecation") - public MappingCouchbaseConverter(CouchbaseFactory couchbaseFactory, - MappingContext, + public MappingCouchbaseConverter(MappingContext, CouchbasePersistentProperty> mappingContext) { super(ConversionServiceFactory.createDefaultConversionService()); this.mappingContext = mappingContext; } + @Override public MappingContext, CouchbasePersistentProperty> getMappingContext() { return mappingContext; } + @Override public R read(Class type, Object s) { throw new UnsupportedOperationException("Not supported yet."); } - public void write(Object t, Object s) { - throw new UnsupportedOperationException("Not supported yet."); + @Override + public void write(Object source, Object target) { + if(source == null) { + return; + } + + TypeInformation type = ClassTypeInformation.from(source.getClass()); + writeInternal(source, target, type); } + protected void writeInternal(Object source, Object target, TypeInformation type) { + System.out.println(type.getActualType()); + } + + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; diff --git a/src/main/java/com/couchbase/spring/core/mapping/BasicCouchbasePersistentEntity.java b/src/main/java/com/couchbase/spring/core/mapping/BasicCouchbasePersistentEntity.java index 23d80321..1a3c4a11 100644 --- a/src/main/java/com/couchbase/spring/core/mapping/BasicCouchbasePersistentEntity.java +++ b/src/main/java/com/couchbase/spring/core/mapping/BasicCouchbasePersistentEntity.java @@ -43,6 +43,7 @@ public class BasicCouchbasePersistentEntity this.context = new StandardEvaluationContext(); } + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context.addPropertyAccessor(new BeanFactoryAccessor());