From fe0dd25e16055463de62d3c43f5b0c05a1eaaa75 Mon Sep 17 00:00:00 2001 From: gotty Date: Thu, 20 Dec 2018 19:13:00 +0300 Subject: [PATCH] [LIB-9] Implementation SPI for services, managers and adapters --- .../hedgecode/chess/service/ServiceRegistry.java | 96 ++++++++++++++++++++++ .../chess/service/ServiceRegistryException.java | 47 +++++++++++ .../chess/service/jpa/JpaAuthorService.java | 6 +- .../chess/service/jpa/JpaDomainService.java | 32 ++------ .../chess/service/jpa/JpaEtudeService.java | 10 +-- .../chess/service/jpa/JpaEtudeTypeService.java | 4 +- .../org.hedgecode.chess.domain.AuthorAdapter | 1 + .../org.hedgecode.chess.domain.EtudeAdapter | 2 + .../org.hedgecode.chess.domain.EtudeTypeAdapter | 1 + ....hedgecode.chess.persistence.PersistenceManager | 1 + .../org.hedgecode.chess.service.AuthorService | 1 + .../org.hedgecode.chess.service.EtudeService | 1 + .../org.hedgecode.chess.service.EtudeTypeService | 1 + .../chess/service/LocalStrings.properties | 21 +++++ .../chess/service/LocalStrings_ru.properties | 20 +++++ 15 files changed, 208 insertions(+), 36 deletions(-) create mode 100644 chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistry.java create mode 100644 chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistryException.java create mode 100644 chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.AuthorAdapter create mode 100644 chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeAdapter create mode 100644 chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeTypeAdapter create mode 100644 chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.persistence.PersistenceManager create mode 100644 chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.AuthorService create mode 100644 chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeService create mode 100644 chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeTypeService create mode 100644 chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings.properties create mode 100644 chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings_ru.properties 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 index 0000000..a892bb9 --- /dev/null +++ b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistry.java @@ -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 Iterator providers(Class serviceClass) { + final Iterator providers = ServiceLoader.load(serviceClass).iterator(); + + if (!providers.hasNext()) { + throw new ServiceRegistryException("service.provider.not.found", serviceClass.getName()); + } + + return providers; + } + + public static ServiceType singleProvider(Class serviceClass) { + final Iterator providers = providers(serviceClass); + + ServiceType provider = providers.next(); + if (providers.hasNext()) { + throw new ServiceRegistryException("service.too.many.providers", serviceClass.getName()); + } + + return provider; + } + + public static AdapterType singleAdapter( + Class adapterClass, + Class targetClass) + { + AdapterType targetAdapter = null; + + final Iterator 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 index 0000000..f1fd76c --- /dev/null +++ b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/ServiceRegistryException.java @@ -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 + ) + ); + } + +} diff --git a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaAuthorService.java b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaAuthorService.java index 3033337..cbf3804 100644 --- a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaAuthorService.java +++ b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaAuthorService.java @@ -49,7 +49,7 @@ public class JpaAuthorService extends JpaDomainService 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 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 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(); } diff --git a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaDomainService.java b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaDomainService.java index 37a4dcb..20c5101 100644 --- a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaDomainService.java +++ b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaDomainService.java @@ -17,10 +17,11 @@ 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 implements DomainService { - // 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 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(); - } - - } - } diff --git a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeService.java b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeService.java index 79a701e..5baaadd 100644 --- a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeService.java +++ b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeService.java @@ -51,7 +51,7 @@ public class JpaEtudeService extends JpaDomainService 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 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 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 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 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(); } diff --git a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeTypeService.java b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeTypeService.java index adf4b13..1c9eadb 100644 --- a/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeTypeService.java +++ b/chesshog-db-etude/src/main/java/org/hedgecode/chess/service/jpa/JpaEtudeTypeService.java @@ -50,7 +50,7 @@ public class JpaEtudeTypeService extends JpaDomainService 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 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 index 0000000..a3f28ba --- /dev/null +++ b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.AuthorAdapter @@ -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 index 0000000..f5db0d5 --- /dev/null +++ b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeAdapter @@ -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 index 0000000..5cf12a2 --- /dev/null +++ b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.domain.EtudeTypeAdapter @@ -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 index 0000000..a06389a --- /dev/null +++ b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.persistence.PersistenceManager @@ -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 index 0000000..4f6a007 --- /dev/null +++ b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.AuthorService @@ -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 index 0000000..98c489a --- /dev/null +++ b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeService @@ -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 index 0000000..7a40a78 --- /dev/null +++ b/chesshog-db-etude/src/main/resources/META-INF/services/org.hedgecode.chess.service.EtudeTypeService @@ -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 index 0000000..02e9635 --- /dev/null +++ b/chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings.properties @@ -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 index 0000000..1c9df63 --- /dev/null +++ b/chesshog-db-etude/src/main/resources/org/hedgecode/chess/service/LocalStrings_ru.properties @@ -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 -- 2.10.0