[POLICY-6] add missing license information
[policy/drools-pdp.git] / policy-utils / src / main / java / org / openecomp / policy / drools / utils / OrderedServiceImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * policy-utils
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.policy.drools.utils;
22
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.HashMap;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.ServiceLoader;
29
30 /**
31  * This class is a template for building a sorted list of service instances,
32  * which are discovered and created using 'ServiceLoader'. 
33  */
34 public class OrderedServiceImpl<T extends OrderedService>
35 {
36   // sorted list of instances implementing the service
37   private List<T> implementers = null;
38
39   // 'ServiceLoader' that is used to discover and create the services
40   private ServiceLoader<T> serviceLoader = null; //ServiceLoader.load(T.class);
41
42   /**
43    * Constructor - create the 'ServiceLoader' instance
44    *
45    * @param clazz the class object associated with 'T' (I supposed it could
46    *    be a subclass, but I'm not sure this is useful)
47    */
48   public OrderedServiceImpl(Class clazz)
49   {
50         // This constructor wouldn't be needed if 'T.class' was legal
51         serviceLoader = ServiceLoader.load(clazz);
52   }
53
54   /**
55    * @return the sorted list of services implementing interface 'T' discovered
56    *    by 'ServiceLoader'.
57    */
58   public synchronized List<T> getList()
59   {
60         if (implementers == null)
61           {
62                 rebuildList();
63           }
64         return(implementers);
65   }
66
67   /**
68    * This method is called by 'getList', but could also be called directly if
69    * we were running with a 'ClassLoader' that supported the dynamic addition
70    * of JAR files. In this case, it could be invoked in order to discover any
71    * new services implementing interface 'T'. This is probably a relatively
72    * expensive operation in terms of CPU and elapsed time, so it is best if it
73    * isn't invoked too frequently.
74    *
75    * @return the sorted list of services implementing interface 'T' discovered
76    *    by 'ServiceLoader'.
77    */
78   public synchronized List<T> rebuildList()
79   {
80         // build a list of all of the current implementors
81         List<T> tmp = new LinkedList<T>();
82         for (T service : serviceLoader)
83           {
84                 tmp.add((T)getSingleton(service));
85           }
86
87         // Sort the list according to sequence number, and then alphabetically
88         // according to full class name.
89         Collections.sort(tmp, new Comparator<T>()
90                                          {
91                                            public int compare(T o1, T o2)
92                                                  {
93                                                    int s1 = o1.getSequenceNumber();
94                                                    int s2 = o2.getSequenceNumber();
95                                                    int rval;
96                                                    if (s1 < s2)
97                                                          {
98                                                            rval = -1;
99                                                          }
100                                                    else if (s1 > s2)
101                                                          {
102                                                            rval = 1;
103                                                          }
104                                                    else
105                                                          {
106                                                            rval = o1.getClass().getName().compareTo
107                                                                  (o2.getClass().getName());
108                                                          }
109                                                    return(rval);
110                                                  }
111                                          });
112
113         // create an unmodifiable version of this list
114         implementers = Collections.unmodifiableList(tmp);
115         System.out.println("***** OrderedServiceImpl implementers:\n" + implementers);
116         return(implementers);
117   }
118
119   // use this to ensure that we only use one unique instance of each class
120   static private HashMap<Class,OrderedService> classToSingleton =
121         new HashMap<>();
122
123   /**
124    * If a service implements multiple APIs managed by 'ServiceLoader', a
125    * separate instance is created for each API. This method ensures that
126    * the first instance is used in all of the lists.
127    *
128    * @param service this is the object created by ServiceLoader
129    * @return the object to use in place of 'service'. If 'service' is the first
130    *    object of this class created by ServiceLoader, it is returned. If not,
131    *    the object of this class that was initially created is returned
132    *    instead.
133    */
134   static private synchronized OrderedService
135         getSingleton(OrderedService service)
136   {
137         // see if we already have an instance of this class
138         OrderedService rval = classToSingleton.get(service.getClass());
139         if (rval == null)
140           {
141                 // No previous instance of this class exists -- use the supplied
142                 // instance, and place it in the table.
143                 rval = service;
144                 classToSingleton.put(service.getClass(), service);
145           }
146         return(rval);
147   }
148 }