You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ad...@apache.org on 2016/11/07 08:25:30 UTC

[7/8] james-project git commit: JAMES-1849 Introduce JPAAnnotationMapper

JAMES-1849 Introduce JPAAnnotationMapper


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/6eea0d4e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/6eea0d4e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/6eea0d4e

Branch: refs/heads/master
Commit: 6eea0d4eac32398d1cbf545272d55c09645b4e32
Parents: 0ca6203
Author: Benoit Tellier <bt...@linagora.com>
Authored: Tue Oct 25 09:36:56 2016 +0200
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Thu Nov 3 15:26:07 2016 +0100

----------------------------------------------------------------------
 mailbox/jpa/pom.xml                             |   1 -
 .../jpa/JPAMailboxSessionMapperFactory.java     |   3 +-
 .../mailbox/jpa/mail/JPAAnnotationMapper.java   | 185 +++++++++++++++++++
 .../jpa/mail/model/JPAMailboxAnnotation.java    | 134 ++++++++++++++
 .../mailbox/jpa/mail/JPAMapperProvider.java     | 129 +++++++++++++
 .../james/mailbox/jpa/mail/JPAMappersTest.java  |  59 ++++++
 .../jpa/mail/TransactionalAnnotationMapper.java |  98 ++++++++++
 7 files changed, 607 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/6eea0d4e/mailbox/jpa/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/jpa/pom.xml b/mailbox/jpa/pom.xml
index 15ffaf6..1217b3d 100644
--- a/mailbox/jpa/pom.xml
+++ b/mailbox/jpa/pom.xml
@@ -93,7 +93,6 @@
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
-            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>

http://git-wip-us.apache.org/repos/asf/james-project/blob/6eea0d4e/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxSessionMapperFactory.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxSessionMapperFactory.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxSessionMapperFactory.java
index 819e92e..4b59206 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxSessionMapperFactory.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxSessionMapperFactory.java
@@ -24,6 +24,7 @@ import javax.persistence.EntityManagerFactory;
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.jpa.mail.JPAAnnotationMapper;
 import org.apache.james.mailbox.jpa.mail.JPAMailboxMapper;
 import org.apache.james.mailbox.jpa.mail.JPAMessageMapper;
 import org.apache.james.mailbox.jpa.user.JPASubscriptionMapper;
@@ -86,7 +87,7 @@ public class JPAMailboxSessionMapperFactory extends MailboxSessionMapperFactory
     @Override
     public AnnotationMapper createAnnotationMapper(MailboxSession session)
             throws MailboxException {
-        throw new NotImplementedException();
+        return new JPAAnnotationMapper(entityManagerFactory);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/6eea0d4e/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAAnnotationMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAAnnotationMapper.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAAnnotationMapper.java
new file mode 100644
index 0000000..4ba35ad
--- /dev/null
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAAnnotationMapper.java
@@ -0,0 +1,185 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.mailbox.jpa.mail;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.NoResultException;
+import javax.persistence.PersistenceException;
+
+import org.apache.james.mailbox.jpa.JPAId;
+import org.apache.james.mailbox.jpa.JPATransactionalMapper;
+import org.apache.james.mailbox.jpa.mail.model.JPAMailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.store.mail.AnnotationMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class JPAAnnotationMapper extends JPATransactionalMapper implements AnnotationMapper {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JPAAnnotationMapper.class);
+
+    public static final Function<JPAMailboxAnnotation, MailboxAnnotation> READ_ROW = new Function<JPAMailboxAnnotation, MailboxAnnotation>() {
+        @Override
+        public MailboxAnnotation apply(JPAMailboxAnnotation input) {
+            return MailboxAnnotation.newInstance(new MailboxAnnotationKey(input.getKey()), input.getValue());
+        }
+    };
+
+    public JPAAnnotationMapper(EntityManagerFactory entityManagerFactory) {
+        super(entityManagerFactory);
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAllAnnotations(MailboxId mailboxId) {
+        JPAId jpaId = (JPAId) mailboxId;
+        return Lists.transform(getEntityManager().createNamedQuery("retrieveAllAnnotations", JPAMailboxAnnotation.class)
+                .setParameter("idParam", jpaId.getRawId()).getResultList(),
+            READ_ROW);
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeys(MailboxId mailboxId, Set<MailboxAnnotationKey> keys) {
+        try {
+            final JPAId jpaId = (JPAId) mailboxId;
+            return ImmutableList.copyOf(Iterables.transform(keys, new Function<MailboxAnnotationKey, MailboxAnnotation>() {
+                @Override
+                public MailboxAnnotation apply(MailboxAnnotationKey input) {
+                    return READ_ROW.apply(
+                        getEntityManager()
+                            .createNamedQuery("retrieveByKey", JPAMailboxAnnotation.class)
+                            .setParameter("idParam", jpaId.getRawId())
+                            .setParameter("keyParam", input.asString())
+                            .getSingleResult());
+                }
+            }));
+        } catch (NoResultException e) {
+            return ImmutableList.of();
+        }
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeysWithOneDepth(MailboxId mailboxId, Set<MailboxAnnotationKey> keys) {
+        return getFilteredLikes((JPAId) mailboxId,
+            keys,
+            new Function<MailboxAnnotationKey, Predicate<MailboxAnnotation>>() {
+                @Override
+                public Predicate<MailboxAnnotation> apply(final MailboxAnnotationKey key) {
+                    return new Predicate<MailboxAnnotation>() {
+                        @Override
+                        public boolean apply(MailboxAnnotation input) {
+                            return key.isParentOrIsEqual(input.getKey());
+                        }
+                    };
+                }
+            });
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeysWithAllDepth(MailboxId mailboxId, Set<MailboxAnnotationKey> keys) {
+        return getFilteredLikes((JPAId) mailboxId,
+            keys,
+            new Function<MailboxAnnotationKey, Predicate<MailboxAnnotation>>() {
+                @Override
+                public Predicate<MailboxAnnotation> apply(final MailboxAnnotationKey key) {
+                    return new Predicate<MailboxAnnotation>() {
+                        @Override
+                        public boolean apply(MailboxAnnotation input) {
+                            return key.isAncestorOrIsEqual(input.getKey());
+                        }
+                    };
+                }
+            });
+    }
+
+    private List<MailboxAnnotation> getFilteredLikes(final JPAId jpaId, Set<MailboxAnnotationKey> keys, final Function<MailboxAnnotationKey, Predicate<MailboxAnnotation>> predicateFunction) {
+        try {
+            return flatMapToList(Iterables.transform(keys,
+                new Function<MailboxAnnotationKey, List<MailboxAnnotation>>() {
+                    @Override
+                    public List<MailboxAnnotation> apply(final MailboxAnnotationKey key) {
+                        return ImmutableList.copyOf(
+                            Iterables.filter(
+                                Iterables.transform(
+                                    getEntityManager()
+                                        .createNamedQuery("retrieveByKeyLike", JPAMailboxAnnotation.class)
+                                        .setParameter("idParam", jpaId.getRawId())
+                                        .setParameter("keyParam", key.asString() + '%')
+                                        .getResultList(),
+                                    READ_ROW),
+                                predicateFunction.apply(key)));
+                    }
+                }));
+        } catch (NoResultException e) {
+            return ImmutableList.of();
+        }
+    }
+
+    private List<MailboxAnnotation> flatMapToList(Iterable<List<MailboxAnnotation>> likes) {
+        ImmutableList.Builder<MailboxAnnotation> resultBuilder = ImmutableList.builder();
+        for (List<MailboxAnnotation> mailboxAnnotations: likes) {
+            resultBuilder.addAll(mailboxAnnotations);
+        }
+        return resultBuilder.build();
+    }
+
+    @Override
+    public void deleteAnnotation(MailboxId mailboxId, MailboxAnnotationKey key) {
+        try {
+            JPAId jpaId = (JPAId) mailboxId;
+            getEntityManager().createNamedQuery("deleteAnnotation")
+                .setParameter("idParam", jpaId.getRawId())
+                .setParameter("key", key.asString())
+                .executeUpdate();
+        } catch (NoResultException e) {
+            LOGGER.debug("Mailbox annotation not found for ID {} and key {}", mailboxId.serialize(), key.asString());
+        } catch (PersistenceException pe) {
+            pe.printStackTrace();
+        }
+    }
+
+    @Override
+    public void insertAnnotation(MailboxId mailboxId, MailboxAnnotation mailboxAnnotation) {
+        Preconditions.checkArgument(!mailboxAnnotation.isNil());
+        JPAId jpaId = (JPAId) mailboxId;
+        if (getAnnotationsByKeys(mailboxId, ImmutableSet.of(mailboxAnnotation.getKey())).isEmpty()) {
+            getEntityManager().persist(
+                new JPAMailboxAnnotation(jpaId.getRawId(),
+                    mailboxAnnotation.getKey().asString(),
+                    mailboxAnnotation.getValue().orNull()));
+        } else {
+            getEntityManager().find(JPAMailboxAnnotation.class,
+                new JPAMailboxAnnotation.JPAMailboxAnnotationId(jpaId.getRawId(), mailboxAnnotation.getKey().asString()))
+                .setValue(mailboxAnnotation.getValue().orNull());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6eea0d4e/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailboxAnnotation.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailboxAnnotation.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailboxAnnotation.java
new file mode 100644
index 0000000..fe9ce8e
--- /dev/null
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/JPAMailboxAnnotation.java
@@ -0,0 +1,134 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.mailbox.jpa.mail.model;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+import com.google.common.base.Objects;
+
+@Entity(name="MailboxAnnotation")
+@Table(name="JAMES_MAILBOX_ANNOTATION")
+@NamedQueries({
+    @NamedQuery(name = "retrieveAllAnnotations", query = "SELECT annotation FROM MailboxAnnotation annotation WHERE annotation.mailboxId = :idParam"),
+    @NamedQuery(name = "retrieveByKey", query = "SELECT annotation FROM MailboxAnnotation annotation WHERE annotation.mailboxId = :idParam AND annotation.key = :keyParam"),
+    @NamedQuery(name = "retrieveByKeyLike", query = "SELECT annotation FROM MailboxAnnotation annotation WHERE annotation.mailboxId = :idParam AND annotation.key LIKE :keyParam"),
+    @NamedQuery(name = "deleteAnnotation", query = "DELETE FROM MailboxAnnotation annotation WHERE annotation.mailboxId = :idParam AND annotation.key = :key")})
+@IdClass(JPAMailboxAnnotation.JPAMailboxAnnotationId.class)
+public class JPAMailboxAnnotation {
+
+    public static final class JPAMailboxAnnotationId {
+        private long mailboxId;
+        private String key;
+
+        public JPAMailboxAnnotationId(long mailboxId, String key) {
+            this.mailboxId = mailboxId;
+            this.key = key;
+        }
+
+        public JPAMailboxAnnotationId() {
+        }
+
+        public long getMailboxId() {
+            return mailboxId;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof JPAMailboxAnnotationId) {
+                JPAMailboxAnnotationId that = (JPAMailboxAnnotationId) o;
+                return Objects.equal(this.mailboxId, that.mailboxId) && Objects.equal(this.key, that.key);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(mailboxId, key);
+        }
+    }
+
+    public static final String MAILBOX_ID = "MAILBOX_ID";
+    public static final String KEY = "KEY";
+    public static final String VALUE = "VALUE";
+
+    @Id
+    @Column(name = MAILBOX_ID)
+    private long mailboxId;
+
+    @Id
+    @Column(name = KEY, length = 200)
+    private String key;
+
+    @Basic()
+    @Column(name = VALUE, length = 200)
+    private String value;
+
+    public JPAMailboxAnnotation() {
+    }
+
+    public JPAMailboxAnnotation(long mailboxId, String key, String value) {
+        this.mailboxId = mailboxId;
+        this.key = key;
+        this.value = value;
+    }
+
+    public long getMailboxId() {
+        return mailboxId;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof JPAMailboxAnnotation) {
+            JPAMailboxAnnotation that = (JPAMailboxAnnotation) o;
+            return Objects.equal(this.mailboxId, that.mailboxId)
+                && Objects.equal(this.key, that.key)
+                && Objects.equal(this.value, that.value);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(mailboxId, key, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6eea0d4e/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMapperProvider.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMapperProvider.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMapperProvider.java
new file mode 100644
index 0000000..3a5b553
--- /dev/null
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMapperProvider.java
@@ -0,0 +1,129 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.mailbox.jpa.mail;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.jpa.JPAId;
+import org.apache.james.mailbox.jpa.mail.model.JPAMailbox;
+import org.apache.james.mailbox.jpa.mail.model.JPAMailboxAnnotation;
+import org.apache.james.mailbox.jpa.mail.model.JPAProperty;
+import org.apache.james.mailbox.jpa.mail.model.JPAUserFlag;
+import org.apache.james.mailbox.jpa.mail.model.openjpa.AbstractJPAMailboxMessage;
+import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMailboxMessage;
+import org.apache.james.mailbox.jpa.user.model.JPASubscription;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.store.mail.AnnotationMapper;
+import org.apache.james.mailbox.store.mail.AttachmentMapper;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
+import org.apache.james.mailbox.store.mail.model.MapperProvider;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+
+import com.google.common.collect.ImmutableList;
+
+public class JPAMapperProvider implements MapperProvider {
+
+    @Override
+    public MailboxMapper createMailboxMapper() throws MailboxException {
+        throw new NotImplementedException();
+    }
+
+    @Override
+    public MessageMapper createMessageMapper() throws MailboxException {
+        throw new NotImplementedException();
+    }
+
+    @Override
+    public AttachmentMapper createAttachmentMapper() throws MailboxException {
+        throw new NotImplementedException();
+    }
+
+    @Override
+    public AnnotationMapper createAnnotationMapper() throws MailboxException {
+        return new TransactionalAnnotationMapper(new JPAAnnotationMapper(createEntityManagerFactory()));
+    }
+
+    @Override
+    public MailboxId generateId() {
+        return JPAId.of(Math.abs(new Random().nextInt()));
+    }
+
+    @Override
+    public MessageId generateMessageId() {
+        return new DefaultMessageId.Factory().generate();
+    }
+
+    @Override
+    public void clearMapper() throws MailboxException {
+        EntityManager entityManager = createEntityManagerFactory().createEntityManager();
+        entityManager.getTransaction().begin();
+        entityManager.createNativeQuery("TRUNCATE table JAMES_MAIL_USERFLAG;");
+        entityManager.createNativeQuery("TRUNCATE table JAMES_MAIL_PROPERTY;");
+        entityManager.createNativeQuery("TRUNCATE table JAMES_MAILBOX_ANNOTATION;");
+        entityManager.createNativeQuery("TRUNCATE table JAMES_MAILBOX;");
+        entityManager.createNativeQuery("TRUNCATE table JAMES_MAIL;");
+        entityManager.getTransaction().commit();
+        entityManager.close();
+    }
+
+    @Override
+    public void ensureMapperPrepared() throws MailboxException {
+
+    }
+
+    @Override
+    public boolean supportPartialAttachmentFetch() {
+        return false;
+    }
+
+    private EntityManagerFactory createEntityManagerFactory() {
+        HashMap<String, String> properties = new HashMap<String, String>();
+        properties.put("openjpa.ConnectionDriverName", "org.h2.Driver");
+        properties.put("openjpa.ConnectionURL", "jdbc:h2:mem:imap;DB_CLOSE_DELAY=-1");
+        properties.put("openjpa.Log", "JDBC=WARN, SQL=WARN, Runtime=WARN");
+        properties.put("openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=72");
+        properties.put("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)");
+        properties.put("openjpa.MetaDataFactory", "jpa(Types=" +
+            JPAMailbox.class.getName() + ";" +
+            AbstractJPAMailboxMessage.class.getName() + ";" +
+            JPAMailboxMessage.class.getName() + ";" +
+            JPAProperty.class.getName() + ";" +
+            JPAUserFlag.class.getName() + ";" +
+            JPAMailboxAnnotation.class.getName() + ";" +
+            JPASubscription.class.getName() + ")");
+
+        return OpenJPAPersistence.getEntityManagerFactory(properties);
+    }
+
+    @Override
+    public List<Capabilities> getNotImplemented() {
+        return ImmutableList.of(Capabilities.MAILBOX, Capabilities.MESSAGE, Capabilities.ATTACHMENT);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6eea0d4e/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMappersTest.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMappersTest.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMappersTest.java
new file mode 100644
index 0000000..99b6def
--- /dev/null
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JPAMappersTest.java
@@ -0,0 +1,59 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.mailbox.jpa.mail;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.junit.runner.RunWith;
+import org.xenei.junit.contract.Contract;
+import org.xenei.junit.contract.ContractImpl;
+import org.xenei.junit.contract.ContractSuite;
+import org.xenei.junit.contract.IProducer;
+
+import com.google.common.base.Throwables;
+
+@RunWith(ContractSuite.class)
+@ContractImpl(JPAMapperProvider.class)
+public class JPAMappersTest {
+
+    private IProducer<JPAMapperProvider> producer = new IProducer<JPAMapperProvider>() {
+
+        private final JPAMapperProvider jpaMapperProvider = new JPAMapperProvider();
+
+        @Override
+        public JPAMapperProvider newInstance() {
+            return jpaMapperProvider;
+        }
+
+        @Override
+        public void cleanUp() {
+            try {
+                jpaMapperProvider.clearMapper();
+            } catch (MailboxException e) {
+                throw Throwables.propagate(e);
+            }
+        }
+    };
+
+    @Contract.Inject
+    public IProducer<JPAMapperProvider> getProducer() {
+        return producer;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6eea0d4e/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalAnnotationMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalAnnotationMapper.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalAnnotationMapper.java
new file mode 100644
index 0000000..06cc7cb
--- /dev/null
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/TransactionalAnnotationMapper.java
@@ -0,0 +1,98 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.mailbox.jpa.mail;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxAnnotation;
+import org.apache.james.mailbox.model.MailboxAnnotationKey;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.store.mail.AnnotationMapper;
+
+import com.google.common.base.Throwables;
+
+public class TransactionalAnnotationMapper implements AnnotationMapper {
+    private final JPAAnnotationMapper wrapped;
+
+    public TransactionalAnnotationMapper(JPAAnnotationMapper wrapped) {
+        this.wrapped = wrapped;
+    }
+
+    @Override
+    public void endRequest() {
+        throw new NotImplementedException();
+    }
+
+    @Override
+    public <T> T execute(Transaction<T> transaction) throws MailboxException {
+        throw new NotImplementedException();
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAllAnnotations(MailboxId mailboxId) {
+        return wrapped.getAllAnnotations(mailboxId);
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeys(MailboxId mailboxId, Set<MailboxAnnotationKey> keys) {
+        return wrapped.getAnnotationsByKeys(mailboxId, keys);
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeysWithOneDepth(MailboxId mailboxId, Set<MailboxAnnotationKey> keys) {
+        return wrapped.getAnnotationsByKeysWithOneDepth(mailboxId, keys);
+    }
+
+    @Override
+    public List<MailboxAnnotation> getAnnotationsByKeysWithAllDepth(MailboxId mailboxId, Set<MailboxAnnotationKey> keys) {
+        return wrapped.getAnnotationsByKeysWithAllDepth(mailboxId, keys);
+    }
+
+    @Override
+    public void deleteAnnotation(final MailboxId mailboxId, final MailboxAnnotationKey key) {
+        try {
+            wrapped.execute(new VoidTransaction() {
+                @Override
+                public void runVoid() throws MailboxException {
+                    wrapped.deleteAnnotation(mailboxId, key);
+                }
+            });
+        } catch (MailboxException e) {
+            Throwables.propagate(e);
+        }
+    }
+
+    @Override
+    public void insertAnnotation(final MailboxId mailboxId, final MailboxAnnotation mailboxAnnotation) {
+        try {
+            wrapped.execute(new VoidTransaction() {
+                @Override
+                public void runVoid() throws MailboxException {
+                    wrapped.insertAnnotation(mailboxId, mailboxAnnotation);
+                }
+            });
+        } catch (MailboxException e) {
+            Throwables.propagate(e);
+        }
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org