[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / openecomp-be / lib / openecomp-core-lib / openecomp-facade-lib / openecomp-facade-api / src / main / java / org / openecomp / core / factory / impl / AbstractFactoryBase.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.core.factory.impl;
22
23
24 import static org.openecomp.core.utilities.CommonMethods.isEmpty;
25 import static org.openecomp.core.utilities.CommonMethods.newInstance;
26
27 import org.openecomp.sdc.common.errors.CoreException;
28 import org.openecomp.sdc.common.errors.ErrorCategory;
29 import org.openecomp.sdc.common.errors.ErrorCode;
30
31 import java.util.Collection;
32 import java.util.Map;
33 import java.util.concurrent.ConcurrentHashMap;
34
35 public abstract class AbstractFactoryBase {
36
37   /**
38    * Temporary registry of default implementations. The map keeps class names rather then class
39    * types to allow unloading of those classes from memory by garbage collector if factory is not
40    * actually used.
41    */
42   private static Map<String, String> registry = new ConcurrentHashMap<String, String>();
43
44   /**
45    * Cached factory instances.
46    */
47   private static Map<String, AbstractFactoryBase> factoryMap =
48       new ConcurrentHashMap<String, AbstractFactoryBase>();
49
50   /**
51    * Registers implementor for an abstract factory. The method accepts Java classes rather then
52    * class names to ensure type safety at compilation time.
53    *
54    * @param <I>     Java interface type instantiated by abstract factory
55    * @param <F>     Type specific abstract factory for concrete Java interface
56    * @param factory Java class of a type specific abstract factory
57    * @param impl    Java class of type specific factory implementor
58    */
59   public static <I, F extends AbstractFactoryBase> void registerFactory(Class<F> factory,
60                                                                         Class<? extends F> impl) {
61     if (factory == null) {
62       throw new CoreException(
63           new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input factory.")
64               .withCategory(ErrorCategory.SYSTEM).build());
65     }
66
67     if (impl == null) {
68       throw new CoreException(
69           new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input impl.")
70               .withCategory(ErrorCategory.SYSTEM).build());
71     }
72     if (factoryMap != null && factoryMap.containsKey(factory.getName())) {
73       factoryMap.remove(factory.getName());
74     }
75     registry.put(factory.getName(), impl.getName());
76   } // registerFactory
77
78   // TODO: Remove
79   protected static void registerFactory(String factoryName, String implName) {
80     registry.put(factoryName, implName);
81   } // registerFactory
82
83   /**
84    * Unregister factory.
85    *
86    * @param <F>     the type parameter
87    * @param factory the factory
88    */
89   public static <F extends AbstractFactoryBase> void unregisterFactory(Class<F> factory) {
90     if (factory == null) {
91       throw new CoreException(
92           new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input factory.")
93               .withCategory(ErrorCategory.SYSTEM).build());
94     }
95     if (factoryMap != null) {
96       factoryMap.remove(factory.getName());
97     }
98   }
99
100   /**
101    * Instantiates the configured implementation of an abstract factory.
102    *
103    * @param <I>         Java interface type instantiated by abstract factory
104    * @param <F>         Type specific abstract factory for concrete Java interface
105    * @param factoryType Java class of type specific abstract factory
106    * @return Instance of implementation class
107    */
108   @SuppressWarnings("unchecked")
109   public static <I, F extends AbstractFactoryBase> F getInstance(Class<F> factoryType) {
110     if (factoryType == null) {
111       throw new CoreException(
112           new ErrorCode.ErrorCodeBuilder().withId("E0001")
113               .withMessage("Mandatory input factory type.").withCategory(ErrorCategory.SYSTEM)
114               .build());
115
116     }
117     // Pick up factory instance from cache
118     F factory = (F) factoryMap.get(factoryType.getName());
119     // Check for the first time access
120     if (factory == null) {
121       // Synchronize factory instantiation
122       synchronized (factoryType) {
123         // Re-check the factory instance
124         factory = (F) factoryMap.get(factoryType.getName());
125         if (factory == null) {
126           // Get the implementation class name
127           String implName = registry.get(factoryType.getName());
128
129           if (isEmpty(implName)) {
130             throw new CoreException(
131                 new ErrorCode.ErrorCodeBuilder().withId("E0001")
132                     .withMessage("Mandatory input factory implementation.")
133                     .withCategory(ErrorCategory.SYSTEM).build());
134           }
135
136           factory = newInstance(implName, factoryType);
137
138           factory.init();
139
140           // Cache the instantiated singleton
141           factoryMap.put(factoryType.getName(), factory);
142         }
143       }
144     }
145
146     return factory;
147
148   } // getInstance
149
150
151   /**
152    * Is factory registered boolean.
153    *
154    * @param <F>         the type parameter
155    * @param factoryType the factory type
156    * @return the boolean
157    */
158   public static <F extends AbstractFactoryBase> boolean isFactoryRegistered(Class<F> factoryType) {
159     boolean isFactoryRegistered = false;
160     if (factoryType == null) {
161       throw new CoreException(
162           new ErrorCode.ErrorCodeBuilder().withId("E0001")
163               .withMessage("Mandatory input factory type.").withCategory(ErrorCategory.SYSTEM)
164               .build());
165     }
166     // Pick up factory instance from cache
167     F factory = (F) factoryMap.get(factoryType.getName());
168     // Check for the first time access
169     if (factory != null) {
170       isFactoryRegistered = true;
171     } else {
172       // Get the implementation class name
173       String implName = registry.get(factoryType.getName());
174       if (!isEmpty(implName)) {
175         isFactoryRegistered = true;
176       }
177     }
178     return isFactoryRegistered;
179   }
180
181   /**
182    * Stop all.
183    */
184   public static void stopAll() {
185     Collection<AbstractFactoryBase> factorylist = factoryMap.values();
186     for (AbstractFactoryBase factory : factorylist) {
187       factory.stop();
188     }
189   }
190
191   protected void init() {
192   }
193
194   protected void stop() {
195   }
196
197 }