From 339cc722acfd93c53a33012cfa237ab3b53c6904 Mon Sep 17 00:00:00 2001 From: Nagy Attila Gabor Date: Sat, 26 Jan 2019 16:23:15 +0100 Subject: [PATCH] Made implementation classes configurable from the respective properties file This way implementation classes for EV/SE side controllers could be replaced without touching the mainline code. I believe this will simplify forking and extending the project. --- RISE-V2G-EVCC/EVCCConfig.properties | 7 ++ .../evcc/misc/EVCCImplementationFactory.java | 50 +++++++++++ .../session/V2GCommunicationSessionEVCC.java | 4 +- RISE-V2G-SECC/SECCConfig.properties | 9 ++ .../secc/misc/SECCImplementationFactory.java | 84 +++++++++++++++++++ .../session/V2GCommunicationSessionSECC.java | 10 +-- .../shared/misc/V2GImplementationFactory.java | 73 ++++++++++++++++ 7 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/misc/EVCCImplementationFactory.java create mode 100644 RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/misc/SECCImplementationFactory.java create mode 100644 RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GImplementationFactory.java diff --git a/RISE-V2G-EVCC/EVCCConfig.properties b/RISE-V2G-EVCC/EVCCConfig.properties index 53aeb67..e19f8da 100644 --- a/RISE-V2G-EVCC/EVCCConfig.properties +++ b/RISE-V2G-EVCC/EVCCConfig.properties @@ -83,6 +83,13 @@ authentication.mode = # - DC_unique energy.transfermode.requested = AC_three_phase_core +# +# Implementation classes +#--------------------------------------------- +# If you want to replace the implementations the set the following attributes +# to the name of your classes +# When omitted default dummy implementations will be used +implementation.evcc.controller = com.v2gclarity.risev2g.evcc.evController.DummyEVController # XML representation of messages #------------------------------- diff --git a/RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/misc/EVCCImplementationFactory.java b/RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/misc/EVCCImplementationFactory.java new file mode 100644 index 0000000..2807ef2 --- /dev/null +++ b/RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/misc/EVCCImplementationFactory.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * The MIT License (MIT) + * + * Copyright 2017 Dr.-Ing. Marc Mültin (V2G Clarity) + * + * 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 DEALINGS IN + * THE SOFTWARE. + *******************************************************************************/ +package com.v2gclarity.risev2g.evcc.misc; + +import com.v2gclarity.risev2g.evcc.evController.DummyEVController; +import com.v2gclarity.risev2g.evcc.evController.IEVController; +import com.v2gclarity.risev2g.evcc.session.V2GCommunicationSessionEVCC; +import com.v2gclarity.risev2g.shared.misc.V2GImplementationFactory; + +/** + * Implementation factory for the EVCC controller + * + */ +public class EVCCImplementationFactory extends V2GImplementationFactory { + + /** + * Creates the controller for the EVCC application + * @param commSessionContext the session the backend will be connected to + * @return + */ + public static IEVController createEVController(V2GCommunicationSessionEVCC commSessionContext) { + IEVController instance = buildFromProperties("implementation.evcc.controller", IEVController.class, commSessionContext); + if (instance == null) { + return new DummyEVController(commSessionContext); + } else { + return instance; + } + } +} diff --git a/RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/session/V2GCommunicationSessionEVCC.java b/RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/session/V2GCommunicationSessionEVCC.java index e241d39..0a1ff37 100644 --- a/RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/session/V2GCommunicationSessionEVCC.java +++ b/RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/session/V2GCommunicationSessionEVCC.java @@ -28,8 +28,8 @@ import java.util.List; import java.util.Observable; import java.util.Observer; -import com.v2gclarity.risev2g.evcc.evController.DummyEVController; import com.v2gclarity.risev2g.evcc.evController.IEVController; +import com.v2gclarity.risev2g.evcc.misc.EVCCImplementationFactory; import com.v2gclarity.risev2g.evcc.states.WaitForAuthorizationRes; import com.v2gclarity.risev2g.evcc.states.WaitForCableCheckRes; import com.v2gclarity.risev2g.evcc.states.WaitForCertificateInstallationRes; @@ -137,7 +137,7 @@ public class V2GCommunicationSessionEVCC extends V2GCommunicationSession impleme // configure which EV controller implementation to use // TODO the EV controller needs to run as a separate Thread (to receive notifications from the EV and to avoid blocking calls to the controller) - setEvController(new DummyEVController(this)); + setEvController(EVCCImplementationFactory.createEVController(this)); /* * Is needed for measuring the time span between transition to state B (plug-in) and receipt diff --git a/RISE-V2G-SECC/SECCConfig.properties b/RISE-V2G-SECC/SECCConfig.properties index a11668a..5b43ea8 100644 --- a/RISE-V2G-SECC/SECCConfig.properties +++ b/RISE-V2G-SECC/SECCConfig.properties @@ -76,6 +76,15 @@ authentication.modes.supported = Contract, ExternalPayment # - false environment.private = false +# +# Implementation classes +#--------------------------------------------- +# If you want to replace the implementations the set the following attributes +# to the name of your classes +# When omitted default dummy implementations will be used +implementation.secc.backend = com.v2gclarity.risev2g.secc.backend.DummyBackendInterface +implementation.secc.acevsecontroller = com.v2gclarity.risev2g.secc.evseController.DummyACEVSEController +implementation.secc.dcevsecontroller = com.v2gclarity.risev2g.secc.evseController.DummyDCEVSEController # XML representation of messages #------------------------------- diff --git a/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/misc/SECCImplementationFactory.java b/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/misc/SECCImplementationFactory.java new file mode 100644 index 0000000..4d421a6 --- /dev/null +++ b/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/misc/SECCImplementationFactory.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * The MIT License (MIT) + * + * Copyright 2017 Dr.-Ing. Marc Mültin (V2G Clarity) + * + * 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 DEALINGS IN + * THE SOFTWARE. + *******************************************************************************/ +package com.v2gclarity.risev2g.secc.misc; + +import com.v2gclarity.risev2g.secc.backend.DummyBackendInterface; +import com.v2gclarity.risev2g.secc.backend.IBackendInterface; +import com.v2gclarity.risev2g.secc.evseController.DummyACEVSEController; +import com.v2gclarity.risev2g.secc.evseController.DummyDCEVSEController; +import com.v2gclarity.risev2g.secc.evseController.IACEVSEController; +import com.v2gclarity.risev2g.secc.evseController.IDCEVSEController; +import com.v2gclarity.risev2g.secc.session.V2GCommunicationSessionSECC; +import com.v2gclarity.risev2g.shared.misc.V2GImplementationFactory; + +/** + * Implementation factory for the SECC controllers and for the backend interface + * + */ +public class SECCImplementationFactory extends V2GImplementationFactory { + + + /** + * Creates the backend interface for the SECC application + * @param commSessionContext the session the backend will be connected to + * @return + */ + public static IBackendInterface createBackendInterface(V2GCommunicationSessionSECC commSessionContext) { + IBackendInterface instance = buildFromProperties("implementation.secc.backend", IBackendInterface.class, commSessionContext); + if (instance == null) { + return new DummyBackendInterface(commSessionContext); + } else { + return instance; + } + } + + /** + * Creates the AC EVSE controller for the SECC application + * @param commSessionContext the session the backend will be connected to + * @return + */ + public static IACEVSEController createACEVSEController(V2GCommunicationSessionSECC commSessionContext) { + IACEVSEController instance = buildFromProperties("implementation.secc.acevsecontroller", IACEVSEController.class, commSessionContext); + if (instance == null) { + return new DummyACEVSEController(commSessionContext); + } else { + return instance; + } + } + + /** + * Creates the DC EVSE controller for the SECC application + * @param commSessionContext the session the backend will be connected to + * @return + */ + public static IDCEVSEController createDCEVSEController(V2GCommunicationSessionSECC commSessionContext) { + IDCEVSEController instance = buildFromProperties("implementation.secc.dcevsecontroller", IDCEVSEController.class, commSessionContext); + if (instance == null) { + return new DummyDCEVSEController(commSessionContext); + } else { + return instance; + } + } + +} diff --git a/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionSECC.java b/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionSECC.java index a82ee0d..46716ac 100644 --- a/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionSECC.java +++ b/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionSECC.java @@ -29,13 +29,11 @@ import java.util.Arrays; import java.util.Observable; import java.util.Observer; -import com.v2gclarity.risev2g.secc.backend.DummyBackendInterface; import com.v2gclarity.risev2g.secc.backend.IBackendInterface; -import com.v2gclarity.risev2g.secc.evseController.DummyACEVSEController; -import com.v2gclarity.risev2g.secc.evseController.DummyDCEVSEController; import com.v2gclarity.risev2g.secc.evseController.IACEVSEController; import com.v2gclarity.risev2g.secc.evseController.IDCEVSEController; import com.v2gclarity.risev2g.secc.evseController.IEVSEController; +import com.v2gclarity.risev2g.secc.misc.SECCImplementationFactory; import com.v2gclarity.risev2g.secc.states.ForkState; import com.v2gclarity.risev2g.secc.states.WaitForAuthorizationReq; import com.v2gclarity.risev2g.secc.states.WaitForCableCheckReq; @@ -133,11 +131,11 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme setCurrentState(getStartState()); // Configure which EVSE controller implementation to use - setACEvseController(new DummyACEVSEController(this)); - setDCEvseController(new DummyDCEVSEController(this)); + setACEvseController(SECCImplementationFactory.createACEVSEController(this)); + setDCEvseController(SECCImplementationFactory.createDCEVSEController(this)); // Configures which backend interface implementation to use for retrieving SASchedules - setBackendInterface(new DummyBackendInterface(this)); + setBackendInterface(SECCImplementationFactory.createBackendInterface(this)); // ACEVSE notification setAcEVSEStatus(new ACEVSEStatusType()); diff --git a/RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GImplementationFactory.java b/RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GImplementationFactory.java new file mode 100644 index 0000000..3f58231 --- /dev/null +++ b/RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GImplementationFactory.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * The MIT License (MIT) + * + * Copyright 2017 Dr.-Ing. Marc Mültin (V2G Clarity) + * + * 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 DEALINGS IN + * THE SOFTWARE. + *******************************************************************************/ +package com.v2gclarity.risev2g.shared.misc; + +import java.lang.reflect.Constructor; +import java.util.Arrays; + +import com.v2gclarity.risev2g.shared.utils.MiscUtils; + +/** + * This class serves as the base for implementation factory + * classes used in the SE/EV projects + * It will look up and instantiate a class based on a + * configuration property + */ +abstract public class V2GImplementationFactory { + + /** + * Builds an object instance from the configuration properties + * The configuration should hold the class of the instance that + * will be built. + * @param propertyName Name of the property the contains the fully qualified class name + * @param cls Target class of the build instance + * @param params Optional arguments to the constructor + * @return + */ + protected static T buildFromProperties(String propertyName, Class cls, Object...params) { + try { + String className = MiscUtils.getV2gEntityConfig().getProperty(propertyName); + if (className == null) { + return null; + } + + Class clazz = Class.forName(className); + + Class[] paramClasses = Arrays.stream(params) + .map(param -> param.getClass()) + .toArray(size -> new Class[size]); + + Constructor constructor = clazz.getConstructor(paramClasses); + Object instance = constructor.newInstance(params); + if (!cls.isInstance(instance)) { + throw new Exception("Instantiated object is not of excepted type"); + } + return cls.cast(instance); + } catch (Exception e) { + throw new RuntimeException("Could not instantiate implementations class for property " + propertyName, e); + } + } + + +}