From b80736bf60f16934d55a1bc25a439c3e1ef2619f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Basl=C3=A9?= Date: Sat, 27 Jun 2015 14:31:33 +0200 Subject: [PATCH] parse translationService and utility methods in template --- .../config/CouchbaseNamespaceHandler.java | 2 +- .../CouchbaseTranslationServiceParser.java | 78 ++++++++++++++ .../couchbase/core/CouchbaseOperations.java | 9 ++ .../couchbase/core/CouchbaseTemplate.java | 101 +++++++++++++++++- 4 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/springframework/data/couchbase/config/CouchbaseTranslationServiceParser.java diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java index ee2ae154..13959f4c 100644 --- a/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java @@ -39,7 +39,7 @@ public class CouchbaseNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("bucket", new CouchbaseBucketParser()); registerBeanDefinitionParser("jmx", new CouchbaseJmxParser()); registerBeanDefinitionParser("template", new CouchbaseTemplateParser()); - //TODO translation service + registerBeanDefinitionParser("translation-service", new CouchbaseTranslationServiceParser()); } } diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseTranslationServiceParser.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseTranslationServiceParser.java new file mode 100644 index 00000000..d311789e --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseTranslationServiceParser.java @@ -0,0 +1,78 @@ +/* + * Copyright 2012-2015 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.couchbase.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.w3c.dom.Element; + +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService; +import org.springframework.util.StringUtils; + +/** + * Enables Parsing of the "" configuration bean. + * + * @author David Harrigan + */ +public class CouchbaseTranslationServiceParser extends AbstractSingleBeanDefinitionParser { + + /** + * Defines the bean class that will be constructed. + * + * @param element the XML element which contains the attributes. + * @return the class type to instantiate. + */ + @Override + protected Class getBeanClass(final Element element) { + return JacksonTranslationService.class; + } + + /** + * Parse the bean definition and build up the bean. + * + * @param element the XML element which contains the attributes. + * @param bean the builder which builds the bean. + */ + @Override + protected void doParse(final Element element, final BeanDefinitionBuilder bean) { + final String objectMapper = element.getAttribute("objectMapper"); + if (StringUtils.hasText(objectMapper)) { + bean.addPropertyReference("objectMapper", objectMapper); + } + else { + bean.addPropertyValue("objectMapper", new ObjectMapper()); + } + } + + /** + * Resolve the bean ID and assign a default if not set. + * + * @param element the XML element which contains the attributes. + * @param definition the bean definition to work with. + * @param parserContext encapsulates the parsing state and configuration. + * @return the ID to work with (e.g., "translationService") + */ + @Override + protected String resolveId(final Element element, final AbstractBeanDefinition definition, final ParserContext parserContext) { + String id = super.resolveId(element, definition, parserContext); + return StringUtils.hasText(id) ? id : BeanNames.TRANSLATION_SERVICE; + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java index dddf0427..c403ebbd 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java @@ -19,6 +19,8 @@ package org.springframework.data.couchbase.core; import com.couchbase.client.java.Bucket; +import org.springframework.data.couchbase.core.convert.CouchbaseConverter; + /** * Defines common operations on the Couchbase data source, most commonly implemented by {@link CouchbaseTemplate}. * @@ -34,4 +36,11 @@ public interface CouchbaseOperations { */ Bucket getCouchbaseBucket(); + /** + * Returns the underlying {@link CouchbaseConverter}. + * + * @return CouchbaseConverter. + */ + CouchbaseConverter getConverter(); + } diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java index d7c31083..9968028b 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java @@ -16,12 +16,25 @@ package org.springframework.data.couchbase.core; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + import com.couchbase.client.java.Bucket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.data.couchbase.core.convert.CouchbaseConverter; +import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter; +import org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService; +import org.springframework.data.couchbase.core.convert.translation.TranslationService; +import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext; +import org.springframework.data.couchbase.core.mapping.CouchbaseStorable; /** * @author Michael Nitschinger @@ -31,13 +44,94 @@ import org.springframework.context.ApplicationEventPublisherAware; public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventPublisherAware { private static final Logger LOGGER = LoggerFactory.getLogger(CouchbaseTemplate.class); + private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking.NONE; + private static final Collection ITERABLE_CLASSES; + static { + final Set iterableClasses = new HashSet(); + iterableClasses.add(List.class.getName()); + iterableClasses.add(Collection.class.getName()); + iterableClasses.add(Iterator.class.getName()); + ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses); + } private final Bucket client; + private final CouchbaseConverter converter; + private final TranslationService translationService; + private ApplicationEventPublisher eventPublisher; + private WriteResultChecking writeResultChecking = DEFAULT_WRITE_RESULT_CHECKING; public CouchbaseTemplate(final Bucket client) { + this(client, null, null); + } + + public CouchbaseTemplate(final Bucket client, final CouchbaseConverter converter) { + this(client, converter, null); + } + + public CouchbaseTemplate(final Bucket client, final CouchbaseConverter converter, + final TranslationService translationService) { this.client = client; + this.converter = converter == null ? getDefaultConverter() : converter; + this.translationService = translationService == null ? getDefaultTranslationService() : translationService; + } + + private TranslationService getDefaultTranslationService() { + JacksonTranslationService t = new JacksonTranslationService(); + t.afterPropertiesSet(); + return t; + } + + private CouchbaseConverter getDefaultConverter() { + MappingCouchbaseConverter c = new MappingCouchbaseConverter(new CouchbaseMappingContext()); + c.afterPropertiesSet(); + return c; + } + + /** Encode a {@link CouchbaseStorable} into a storable representation (JSON) **/ + private Object translateEncode(final CouchbaseStorable source) { + return translationService.encode(source); + } + + + /** Decode a JSON string into a {@link CouchbaseStorable} **/ + private CouchbaseStorable translateDecode(final String source, final CouchbaseStorable target) { + return translationService.decode(source, target); + } + + /** + * Make sure the given object is not a iterable. + * + * @param o the object to verify. + */ + protected static void ensureNotIterable(Object o) { + if (null != o) { + if (o.getClass().isArray() || ITERABLE_CLASSES.contains(o.getClass().getName())) { + throw new IllegalArgumentException("Cannot use a collection here."); + } + } + } + + /** + * Handle write errors according to the set {@link #writeResultChecking} setting. + * + * @param message the message to use. + */ + private void handleWriteResultError(String message) { + if (writeResultChecking == WriteResultChecking.NONE) { + return; + } + + if (writeResultChecking == WriteResultChecking.EXCEPTION) { + throw new CouchbaseDataIntegrityViolationException(message); + } else { + LOGGER.error(message); + } + } + + public void setWriteResultChecking(WriteResultChecking writeResultChecking) { + this.writeResultChecking = writeResultChecking == null ? DEFAULT_WRITE_RESULT_CHECKING : writeResultChecking; } @Override @@ -47,6 +141,11 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP @Override public Bucket getCouchbaseBucket() { - return client; + return this.client; + } + + @Override + public CouchbaseConverter getConverter() { + return this.converter; } }