2 * Copyright © 2016-2017 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.core.factory.impl;
20 import org.apache.commons.lang3.StringUtils;
21 import org.openecomp.sdc.common.errors.CoreException;
22 import org.openecomp.sdc.common.errors.ErrorCategory;
23 import org.openecomp.sdc.common.errors.ErrorCode;
25 import java.util.Collection;
27 import java.util.concurrent.ConcurrentHashMap;
29 import static org.openecomp.core.utilities.CommonMethods.newInstance;
31 public abstract class AbstractFactoryBase {
34 * Temporary registry of default implementations. The map keeps class names rather then class
35 * types to allow unloading of those classes from memory by garbage collector if factory is not
38 private static final Map<String, String> REGISTRY = new ConcurrentHashMap<>();
41 * Cached factory instances.
43 private static final Map<String, AbstractFactoryBase> FACTORY_MAP = new ConcurrentHashMap<>();
46 * Registers implementor for an abstract factory. The method accepts Java classes rather then
47 * class names to ensure type safety at compilation time.
49 * @param <I> Java interface type instantiated by abstract factory
50 * @param <F> Type specific abstract factory for concrete Java interface
51 * @param factory Java class of a type specific abstract factory
52 * @param impl Java class of type specific factory implementor
54 public static <I, F extends AbstractFactoryBase> void registerFactory(Class<F> factory,
55 Class<? extends F> impl) {
56 if (factory == null) {
57 throw new CoreException(
58 new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input factory.")
59 .withCategory(ErrorCategory.SYSTEM).build());
63 throw new CoreException(
64 new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input impl.")
65 .withCategory(ErrorCategory.SYSTEM).build());
67 if (FACTORY_MAP.containsKey(factory.getName())) {
68 FACTORY_MAP.remove(factory.getName());
70 REGISTRY.put(factory.getName(), impl.getName());
74 protected static void registerFactory(String factoryName, String implName) {
75 REGISTRY.put(factoryName, implName);
81 * @param <F> the type parameter
82 * @param factory the factory
84 public static <F extends AbstractFactoryBase> void unregisterFactory(Class<F> factory) {
85 if (factory == null) {
86 throw new CoreException(
87 new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input factory.")
88 .withCategory(ErrorCategory.SYSTEM).build());
91 FACTORY_MAP.remove(factory.getName());
95 * Instantiates the configured implementation of an abstract factory.
97 * @param <I> Java interface type instantiated by abstract factory
98 * @param <F> Type specific abstract factory for concrete Java interface
99 * @param factoryType Java class of type specific abstract factory
100 * @return Instance of implementation class
102 @SuppressWarnings("unchecked")
103 public static <I, F extends AbstractFactoryBase> F getInstance(Class<F> factoryType) {
104 if (factoryType == null) {
105 throw new CoreException(
106 new ErrorCode.ErrorCodeBuilder().withId("E0001")
107 .withMessage("Mandatory input factory type.").withCategory(ErrorCategory.SYSTEM)
111 // Pick up factory instance from cache
112 F factory = (F) FACTORY_MAP.get(factoryType.getName());
113 // Check for the first time access
114 if (factory == null) {
115 // Synchronize factory instantiation
116 synchronized (factoryType) {
117 // Re-check the factory instance
118 factory = (F) FACTORY_MAP.get(factoryType.getName());
119 if (factory == null) {
120 // Get the implementation class name
121 String implName = REGISTRY.get(factoryType.getName());
123 if (StringUtils.isEmpty(implName)) {
124 throw new CoreException(
125 new ErrorCode.ErrorCodeBuilder().withId("E0001")
126 .withMessage("Mandatory input factory implementation.")
127 .withCategory(ErrorCategory.SYSTEM).build());
130 factory = newInstance(implName, factoryType);
134 // Cache the instantiated singleton
135 FACTORY_MAP.put(factoryType.getName(), factory);
146 * Is factory registered boolean.
148 * @param <F> the type parameter
149 * @param factoryType the factory type
150 * @return the boolean
152 public static <F extends AbstractFactoryBase> boolean isFactoryRegistered(Class<F> factoryType) {
153 boolean isFactoryRegistered = false;
154 if (factoryType == null) {
155 throw new CoreException(
156 new ErrorCode.ErrorCodeBuilder().withId("E0001")
157 .withMessage("Mandatory input factory type.").withCategory(ErrorCategory.SYSTEM)
160 // Pick up factory instance from cache
161 F factory = (F) FACTORY_MAP.get(factoryType.getName());
162 // Check for the first time access
163 if (factory != null) {
164 isFactoryRegistered = true;
166 // Get the implementation class name
167 String implName = REGISTRY.get(factoryType.getName());
168 if (StringUtils.isNotEmpty(implName)) {
169 isFactoryRegistered = true;
172 return isFactoryRegistered;
178 public static void stopAll() {
179 Collection<AbstractFactoryBase> factorylist = FACTORY_MAP.values();
180 for (AbstractFactoryBase factory : factorylist) {
185 protected void init() {
186 // allows custom initialization
190 protected void stop() {
191 // allows custom shutdown