[LIB-9] Implementation SPI for services, managers and adapters
authorgotty <gotty@hedgecode.org>
Thu, 20 Dec 2018 16:13:00 +0000 (19:13 +0300)
committergotty <gotty@hedgecode.org>
Thu, 20 Dec 2018 16:13:00 +0000 (19:13 +0300)
15 files changed:
chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistry.java [new file with mode: 0644]
chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistryException.java [new file with mode: 0644]
chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaAuthorService.java
chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaDomainService.java
chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeService.java
chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeTypeService.java
chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.AuthorAdapter [new file with mode: 0644]
chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeAdapter [new file with mode: 0644]
chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeTypeAdapter [new file with mode: 0644]
chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.persistence.PersistenceManager [new file with mode: 0644]
chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.AuthorService [new file with mode: 0644]
chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeService [new file with mode: 0644]
chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeTypeService [new file with mode: 0644]
chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings.properties [new file with mode: 0644]
chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings_ru.properties [new file with mode: 0644]

diff --git a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistry.java b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistry.java
new file mode 100644 (file)
index 0000000..a892bb9
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018. Developed by Hedgecode.
+ *
+ * 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.hedgecode.chess.service;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import org.hedgecode.chess.domain.Adapter;
+import org.hedgecode.chess.domain.EtudeAdapter;
+import org.hedgecode.chess.dto.EtudeDTO;
+import org.hedgecode.chess.persistence.PersistenceManager;
+
+/**
+ * Service Provider Interface (SPI) Registry.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class ServiceRegistry {
+
+    private ServiceRegistry() {
+    }
+
+    public static <ServiceType> Iterator<ServiceType> providers(Class<ServiceType> serviceClass) {
+        final Iterator<ServiceType> providers = ServiceLoader.load(serviceClass).iterator();
+
+        if (!providers.hasNext()) {
+            throw new ServiceRegistryException("service.provider.not.found", serviceClass.getName());
+        }
+
+        return providers;
+    }
+
+    public static <ServiceType> ServiceType singleProvider(Class<ServiceType> serviceClass) {
+        final Iterator<ServiceType> providers = providers(serviceClass);
+
+        ServiceType provider = providers.next();
+        if (providers.hasNext()) {
+            throw new ServiceRegistryException("service.too.many.providers", serviceClass.getName());
+        }
+
+        return provider;
+    }
+
+    public static <AdapterType extends Adapter, TargetType> AdapterType singleAdapter(
+            Class<AdapterType> adapterClass,
+            Class<TargetType> targetClass)
+    {
+        AdapterType targetAdapter = null;
+
+        final Iterator<AdapterType> providers = providers(adapterClass);
+
+        while (providers.hasNext()) {
+            AdapterType adapter = providers.next();
+            if (adapter.getTargetClass().equals(targetClass)) {
+                if (targetAdapter != null)
+                    throw new ServiceRegistryException(
+                            "service.too.many.adapters", adapterClass.getName(), targetClass.getName()
+                    );
+                targetAdapter = adapter;
+            }
+        }
+        if (targetAdapter == null)
+            throw new ServiceRegistryException(
+                    "service.adapter.not.found", adapterClass.getName(), targetClass.getName()
+            );
+
+        return targetAdapter;
+    }
+
+
+    public static void main(String... args) {
+
+        AuthorService as = ServiceRegistry.singleProvider(AuthorService.class);
+        System.out.println(as);
+        PersistenceManager pm = ServiceRegistry.singleProvider(PersistenceManager.class);
+        System.out.println(pm);
+        EtudeAdapter ea = ServiceRegistry.singleAdapter(EtudeAdapter.class, EtudeDTO.class);
+        System.out.println(ea);
+
+    }
+
+}
diff --git a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistryException.java b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistryException.java
new file mode 100644 (file)
index 0000000..f1fd76c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018. Developed by Hedgecode.
+ *
+ * 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.hedgecode.chess.service;
+
+import java.util.ResourceBundle;
+
+import org.hedgecode.chess.EtudeConstants;
+
+/**
+ * Service Provider Interface (SPI) Registry Exception.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class ServiceRegistryException extends RuntimeException {
+
+    private static final ResourceBundle LOCALE_BUNDLE =
+            ResourceBundle.getBundle(EtudeConstants.SERVICE_BUNDLE_FILE);
+
+    public ServiceRegistryException(String localeKey) {
+        super(
+                LOCALE_BUNDLE.getString(localeKey)
+        );
+    }
+
+    public ServiceRegistryException(String localeKey, Object... parameters) {
+        super(
+                String.format(
+                        LOCALE_BUNDLE.getString(localeKey), parameters
+                )
+        );
+    }
+
+}
index 3033337..cbf3804 100644 (file)
@@ -49,7 +49,7 @@ public class JpaAuthorService extends JpaDomainService<Author> implements Author
         Query query = getEntityManager().createNamedQuery(
                 Author.FIND_BY_ID
         );
-        query.setParameter(Author.ID_PROPERTY, id);
+        query.setParameter(Author.ID_PARAMETER, id);
         return (Author) query.getSingleResult();
     }
 
@@ -61,7 +61,7 @@ public class JpaAuthorService extends JpaDomainService<Author> implements Author
         Query query = getEntityManager().createNamedQuery(
                 Author.FIND_BY_NAME
         );
-        query.setParameter(Author.NAME_PROPERTY, name);
+        query.setParameter(Author.NAME_PARAMETER, name);
         return query.getResultList();
     }
 
@@ -73,7 +73,7 @@ public class JpaAuthorService extends JpaDomainService<Author> implements Author
         Query query = getEntityManager().createNamedQuery(
                 Author.FIND_BY_BIRTHDATE
         );
-        query.setParameter(Author.BIRTHDATE_PROPERTY, birthdate);
+        query.setParameter(Author.BIRTHDATE_PARAMETER, birthdate);
         return query.getResultList();
     }
 
index 37a4dcb..20c5101 100644 (file)
 package org.hedgecode.chess.service.jpa;
 
 import javax.persistence.EntityManager;
-import javax.persistence.Persistence;
 
 import org.hedgecode.chess.domain.DomainObject;
+import org.hedgecode.chess.persistence.PersistenceManager;
 import org.hedgecode.chess.service.DomainService;
+import org.hedgecode.chess.service.ServiceRegistry;
 
 /**
  *
@@ -29,15 +30,14 @@ import org.hedgecode.chess.service.DomainService;
  */
 public abstract class JpaDomainService<DomainType extends DomainObject> implements DomainService<DomainType> {
 
-    // todo: maybe single entityManager
-    private DomainManager domainManager;
-
     JpaDomainService() {
-        domainManager = new DomainManager();
     }
 
     EntityManager getEntityManager() {
-        return domainManager.getEntityManager();
+        PersistenceManager persistenceManager = ServiceRegistry.singleProvider(
+                PersistenceManager.class
+        );
+        return persistenceManager.getEntityManager();
     }
 
     @Override
@@ -63,24 +63,4 @@ public abstract class JpaDomainService<DomainType extends DomainObject> implemen
         );
     }
 
-    private class DomainManager {
-
-        private static final String PERSISTENCE_UNIT_NAME = "db-etude-persistence-unit";
-
-        private EntityManager entityManager;
-
-        EntityManager getEntityManager() {
-            if (entityManager == null)
-                createEntityManager();
-            return entityManager;
-        }
-
-        void createEntityManager() {
-            entityManager = Persistence.createEntityManagerFactory(
-                    PERSISTENCE_UNIT_NAME
-            ).createEntityManager();
-        }
-
-    }
-
 }
index 79a701e..5baaadd 100644 (file)
@@ -51,7 +51,7 @@ public class JpaEtudeService extends JpaDomainService<Etude> implements EtudeSer
         Query query = getEntityManager().createNamedQuery(
                 Etude.FIND_BY_ID
         );
-        query.setParameter(Etude.ID_PROPERTY, id);
+        query.setParameter(Etude.ID_PARAMETER, id);
         return (Etude) query.getSingleResult();
     }
 
@@ -63,7 +63,7 @@ public class JpaEtudeService extends JpaDomainService<Etude> implements EtudeSer
         Query query = getEntityManager().createNamedQuery(
                 Etude.FIND_BY_HASH
         );
-        query.setParameter(Etude.HASH_PROPERTY, hash);
+        query.setParameter(Etude.HASH_PARAMETER, hash);
         return query.getResultList();
     }
 
@@ -75,7 +75,7 @@ public class JpaEtudeService extends JpaDomainService<Etude> implements EtudeSer
         Query query = getEntityManager().createNamedQuery(
                 Etude.FIND_BY_TYPE
         );
-        query.setParameter(Etude.TYPE_PROPERTY, etudeType);
+        query.setParameter(Etude.TYPE_PARAMETER, etudeType);
         return query.getResultList();
     }
 
@@ -87,7 +87,7 @@ public class JpaEtudeService extends JpaDomainService<Etude> implements EtudeSer
         Query query = getEntityManager().createNamedQuery(
                 Etude.FIND_BY_AUTHOR
         );
-        query.setParameter(Etude.AUTHOR_PROPERTY, author);
+        query.setParameter(Etude.AUTHOR_PARAMETER, author);
         return query.getResultList();
     }
 
@@ -99,7 +99,7 @@ public class JpaEtudeService extends JpaDomainService<Etude> implements EtudeSer
         Query query = getEntityManager().createNamedQuery(
                 Etude.FIND_BY_BLOB
         );
-        query.setParameter(Etude.BLOB_PROPERTY, blob);
+        query.setParameter(Etude.BLOB_PARAMETER, blob);
         return query.getResultList();
     }
 
index adf4b13..1c9eadb 100644 (file)
@@ -50,7 +50,7 @@ public class JpaEtudeTypeService extends JpaDomainService<EtudeType> implements
         Query query = getEntityManager().createNamedQuery(
                 EtudeType.FIND_BY_ID
         );
-        query.setParameter(EtudeType.ID_PROPERTY, id);
+        query.setParameter(EtudeType.ID_PARAMETER, id);
         return (EtudeType) query.getSingleResult();
     }
 
@@ -62,7 +62,7 @@ public class JpaEtudeTypeService extends JpaDomainService<EtudeType> implements
         Query query = getEntityManager().createNamedQuery(
                 EtudeType.FIND_BY_BRIEF
         );
-        query.setParameter(EtudeType.BRIEF_PROPERTY, brief);
+        query.setParameter(EtudeType.BRIEF_PARAMETER, brief);
         return (EtudeType) query.getSingleResult();
     }
 
diff --git a/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.AuthorAdapter b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.AuthorAdapter
new file mode 100644 (file)
index 0000000..a3f28ba
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.dto.AuthorDTOAdapter
\ No newline at end of file
diff --git a/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeAdapter b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeAdapter
new file mode 100644 (file)
index 0000000..f5db0d5
--- /dev/null
@@ -0,0 +1,2 @@
+org.hedgecode.chess.dto.EtudeDTOAdapter
+org.hedgecode.chess.domain.EtudePGNAdapter
\ No newline at end of file
diff --git a/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeTypeAdapter b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeTypeAdapter
new file mode 100644 (file)
index 0000000..5cf12a2
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.dto.EtudeTypeDTOAdapter
\ No newline at end of file
diff --git a/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.persistence.PersistenceManager b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.persistence.PersistenceManager
new file mode 100644 (file)
index 0000000..a06389a
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.persistence.EnvPersistenceManager
\ No newline at end of file
diff --git a/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.AuthorService b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.AuthorService
new file mode 100644 (file)
index 0000000..4f6a007
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.service.jpa.JpaAuthorService
\ No newline at end of file
diff --git a/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeService b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeService
new file mode 100644 (file)
index 0000000..98c489a
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.service.jpa.JpaEtudeService
\ No newline at end of file
diff --git a/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeTypeService b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeTypeService
new file mode 100644 (file)
index 0000000..7a40a78
--- /dev/null
@@ -0,0 +1 @@
+org.hedgecode.chess.service.jpa.JpaEtudeTypeService
\ No newline at end of file
diff --git a/chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings.properties b/chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings.properties
new file mode 100644 (file)
index 0000000..02e9635
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright (c) 2018. Developed by Hedgecode.
+#
+# 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.
+
+# Default localized string information
+# Localized for Locale en_US
+
+service.provider.not.found=Service provider for %s not found
+service.too.many.providers=Too many service providers for %s
+service.adapter.not.found=Service adapter for %s with target type %s not found
+service.too.many.adapters=Too many service adapters for %s with target type %s
diff --git a/chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings_ru.properties b/chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings_ru.properties
new file mode 100644 (file)
index 0000000..1c9df63
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright (c) 2018. Developed by Hedgecode.
+#
+# 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.
+
+# Localized for Locale ru_RU
+
+service.provider.not.found=\u041F\u043E\u0441\u0442\u0430\u0432\u0449\u0438\u043A \u0441\u0435\u0440\u0432\u0438\u0441\u0430 %s \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D
+service.too.many.providers=\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u043C\u043D\u043E\u0433\u043E \u043F\u043E\u0441\u0442\u0430\u0432\u0449\u0438\u043A\u043E\u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 %s
+service.adapter.not.found=\u0410\u0434\u0430\u043F\u0442\u0435\u0440 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 %s \u0441 \u0446\u0435\u043B\u0435\u0432\u044B\u043C \u0442\u0438\u043F\u043E\u043C %s \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D
+service.too.many.adapters=\u0421\u043B\u0438\u0448\u043A\u043E\u043C \u043C\u043D\u043E\u0433\u043E \u0430\u0434\u0430\u043F\u0442\u0435\u0440\u043E\u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 %s \u0441 \u0446\u0435\u043B\u0435\u0432\u044B\u043C \u0442\u0438\u043F\u043E\u043C %s