push addional code
[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 import static org.openecomp.core.utilities.CommonMethods.isEmpty;
24 import static org.openecomp.core.utilities.CommonMethods.newInstance;
25
26 import org.openecomp.sdc.common.errors.CoreException;
27 import org.openecomp.sdc.common.errors.ErrorCategory;
28 import org.openecomp.sdc.common.errors.ErrorCode;
29
30
31 import java.util.Collection;
32 import java.util.Map;
33 import java.util.concurrent.ConcurrentHashMap;
34
35 /**
36  * The type Abstract factory base.
37  */
38 public abstract class AbstractFactoryBase {
39
40   /**
41    * Temporary registry of default implementations. The map keeps class names rather then class
42    * types to allow unloading of those classes from memory by garbage collector if
43    * factory is not actually used.
44    */
45   private static Map<String, String> registry = new ConcurrentHashMap<String, String>();
46
47   /**
48    * Cached factory instances.
49    */
50   private static Map<String, AbstractFactoryBase> factoryMap =
51       new ConcurrentHashMap<String, AbstractFactoryBase>();
52
53   /**
54    * Registers implementor for an abstract factory. The method accepts Java classes rather
55    * then class names to ensure type safety at compilation time.
56    *
57    * @param <I>     Java interface type instantiated by abstract factory
58    * @param <F>     Type specific abstract factory for concrete Java interface
59    * @param factory Java class of a type specific abstract factory
60    * @param impl    Java class of type specific factory implementor
61    */
62   public static <I, F extends AbstractFactoryBase> void registerFactory(Class<F> factory,
63                                                                         Class<? extends F> impl) {
64     if (factory == null) {
65       throw new CoreException(
66           new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input factory.")
67               .withCategory(ErrorCategory.SYSTEM).build());
68     }
69
70     if (impl == null) {
71       throw new CoreException(
72           new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input impl.")
73               .withCategory(ErrorCategory.SYSTEM).build());
74     }
75     if (factoryMap != null && factoryMap.containsKey(factory.getName())) {
76       factoryMap.remove(factory.getName());
77     }
78     registry.put(factory.getName(), impl.getName());
79   } // registerFactory
80
81   /**
82    * Register factory.
83    *
84    * @param factoryName the factory name
85    * @param implName    the impl name
86    */
87   // TODO: Remove
88   protected static void registerFactory(String factoryName, String implName) {
89     registry.put(factoryName, implName);
90   } // registerFactory
91
92   /**
93    * Unregister factory.
94    *
95    * @param <F>     the type parameter
96    * @param factory the factory
97    */
98   public static <F extends AbstractFactoryBase> void unregisterFactory(Class<F> factory) {
99     if (factory == null) {
100       throw new CoreException(
101           new ErrorCode.ErrorCodeBuilder().withId("E0001").withMessage("Mandatory input factory.")
102               .withCategory(ErrorCategory.SYSTEM).build());
103     }
104     if (factoryMap != null) {
105       factoryMap.remove(factory.getName());
106     }
107   }
108
109   /**
110    * Instantiates the configured implementation of an abstract factory.
111    *
112    * @param <I>         Java interface type instantiated by abstract factory
113    * @param <F>         Type specific abstract factory for concrete Java interface
114    * @param factoryType Java class of type specific abstract factory
115    * @return Instance of implementation class
116    */
117   @SuppressWarnings("unchecked")
118   public static <I, F extends AbstractFactoryBase> F getInstance(Class<F> factoryType) {
119     if (factoryType == null) {
120       throw new CoreException(
121           new ErrorCode.ErrorCodeBuilder().withId("E0001")
122               .withMessage("Mandatory input factory type.").withCategory(ErrorCategory.SYSTEM)
123               .build());
124
125     }
126     // Pick up factory instance from cache
127     F factory = (F) factoryMap.get(factoryType.getName());
128     // Check for the first time access
129     if (factory == null) {
130       // Synchronize factory instantiation
131       synchronized (factoryType) {
132         // Re-check the factory instance
133         factory = (F) factoryMap.get(factoryType.getName());
134         if (factory == null) {
135           // Get the implementation class name
136           String implName = registry.get(factoryType.getName());
137
138           if (isEmpty(implName)) {
139             throw new CoreException(
140                 new ErrorCode.ErrorCodeBuilder().withId("E0001")
141                     .withMessage("Mandatory input factory implementation.")
142                     .withCategory(ErrorCategory.SYSTEM).build());
143           }
144
145           factory = newInstance(implName, factoryType);
146
147           factory.init();
148
149           // Cache the instantiated singleton
150           factoryMap.put(factoryType.getName(), factory);
151         }
152       }
153     }
154
155     return factory;
156
157   } // getInstance
158
159
160   /**
161    * Is factory registered boolean.
162    *
163    * @param <F>         the type parameter
164    * @param factoryType the factory type
165    * @return the boolean
166    */
167   public static <F extends AbstractFactoryBase> boolean isFactoryRegistered(Class<F> factoryType) {
168     boolean isFactoryRegistered = false;
169     if (factoryType == null) {
170       throw new CoreException(
171           new ErrorCode.ErrorCodeBuilder().withId("E0001")
172               .withMessage("Mandatory input factory type.").withCategory(ErrorCategory.SYSTEM)
173               .build());
174     }
175     // Pick up factory instance from cache
176     F factory = (F) factoryMap.get(factoryType.getName());
177     // Check for the first time access
178     if (factory != null) {
179       isFactoryRegistered = true;
180     } else {
181       // Get the implementation class name
182       String implName = registry.get(factoryType.getName());
183       if (!isEmpty(implName)) {
184         isFactoryRegistered = true;
185       }
186     }
187     return isFactoryRegistered;
188   }
189
190   /**
191    * Stop all.
192    */
193   public static void stopAll() {
194     Collection<AbstractFactoryBase> factorylist = factoryMap.values();
195     for (AbstractFactoryBase factory : factorylist) {
196       factory.stop();
197     }
198   }
199
200   /**
201    * Init.
202    */
203   protected void init() {
204   }
205
206   /**
207    * Stop.
208    */
209   protected void stop() {
210   }
211
212 }