AT&T 2.0.19 Code drop, stage 4
[aaf/authz.git] / authz-cass / src / main / java / org / onap / aaf / dao / CachedDAO.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aaf\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 package org.onap.aaf.dao;\r
24 \r
25 import java.util.ArrayList;\r
26 import java.util.List;\r
27 \r
28 import org.onap.aaf.authz.layer.Result;\r
29 import org.onap.aaf.dao.aaf.cass.Status;\r
30 \r
31 import org.onap.aaf.inno.env.Trans;\r
32 \r
33 /**\r
34  * CachedDAO\r
35  * \r
36  * Cache the response of "get" of any DAO.  \r
37  * \r
38  * For simplicity's sake, at this time, we only do this for single Object keys  \r
39  * \r
40  *\r
41  * @param <DATA>\r
42  */\r
43 public class CachedDAO<TRANS extends Trans,D extends DAO<TRANS,DATA>,DATA extends Cacheable> \r
44                 extends Cached<TRANS,DATA> implements DAO_RO<TRANS,DATA>{\r
45 //      private final String dirty_str; \r
46         \r
47         private final D dao;\r
48 \r
49         public CachedDAO(D dao, CIDAO<TRANS> info, int segsize) {\r
50                 super(info, dao.table(), segsize);\r
51                 \r
52                 // Instantiate a new Cache per DAO name (so separate instances use the same cache) \r
53                 this.dao = dao;\r
54                 //read_str = "Cached READ for " + dao.table();\r
55 //              dirty_str = "Cache DIRTY on " + dao.table();\r
56                 if(dao instanceof CassDAOImpl) {\r
57                         ((CassDAOImpl<?,?>)dao).cache = this;\r
58                 }\r
59         }\r
60         \r
61         public static<T extends Trans, DA extends DAO<T,DT>, DT extends Cacheable> \r
62                         CachedDAO<T,DA,DT> create(DA dao, CIDAO<T> info, int segsize) {\r
63                 return new CachedDAO<T,DA,DT>(dao,info, segsize);\r
64         }\r
65 \r
66         public void add(DATA data)  {\r
67                 String key = keyFromObjs(dao.keyFrom(data));\r
68                 List<DATA> list = new ArrayList<DATA>();\r
69                 list.add(data);\r
70                 super.add(key,list);\r
71         }\r
72         \r
73 //      public void invalidate(TRANS trans, Object ... objs)  {\r
74 //              TimeTaken tt = trans.start(dirty_str, Env.SUB);\r
75 //              try {\r
76 //                      super.invalidate(keyFromObjs(objs));\r
77 //              } finally {\r
78 //                      tt.done();\r
79 //              }\r
80 //      }\r
81 \r
82         public static String keyFromObjs(Object ... objs) {\r
83                 String key;\r
84                 if(objs.length==1 && objs[0] instanceof String) {\r
85                         key = (String)objs[0];\r
86                 } else {\r
87                         StringBuilder sb = new StringBuilder();\r
88                         boolean first = true;\r
89                         for(Object o : objs) {\r
90                                 if(o!=null) {\r
91                                         if(first) {\r
92                                             first =false;\r
93                                         } else {\r
94                                             sb.append('|');\r
95                                         }\r
96                                         sb.append(o.toString());\r
97                                 }\r
98                         }\r
99                         key = sb.toString();\r
100                 }\r
101                 return key;\r
102         }\r
103 \r
104         public Result<DATA> create(TRANS trans, DATA data) {\r
105                 Result<DATA> d = dao.create(trans,data);\r
106                 if(d.status==Status.OK) {\r
107                     add(d.value);\r
108                 } else {\r
109                         trans.error().log(d.errorString());\r
110                 }\r
111                 invalidate(trans,data);\r
112                 return d;\r
113         }\r
114 \r
115         protected class DAOGetter implements Getter<DATA> {\r
116                 protected TRANS trans;\r
117                 protected Object objs[];\r
118                 protected D dao;\r
119                 public Result<List<DATA>> result;\r
120 \r
121                 public DAOGetter(TRANS trans, D dao, Object ... objs) {\r
122                         this.trans = trans;\r
123                         this.dao = dao;\r
124                         this.objs = objs;\r
125                 }\r
126                 \r
127                 /**\r
128                  * Separated into single call for easy overloading\r
129                  * @return\r
130                  */\r
131                 public Result<List<DATA>> call() {\r
132                         return dao.read(trans, objs);\r
133                 }\r
134                 \r
135                 @Override\r
136                 public final Result<List<DATA>> get() {\r
137                         return call();\r
138 //                      if(result.isOKhasData()) { // Note, given above logic, could exist, but stale\r
139 //                              return result.value;\r
140 //                      } else {\r
141 //                              return null;\r
142 //                      }\r
143                 }\r
144         }\r
145 \r
146         @Override\r
147         public Result<List<DATA>> read(final TRANS trans, final Object ... objs) {\r
148                 DAOGetter getter = new DAOGetter(trans,dao,objs); \r
149                 return get(trans, keyFromObjs(objs),getter);\r
150 //              if(ld!=null) {\r
151 //                      return Result.ok(ld);//.emptyList(ld.isEmpty());\r
152 //              }\r
153 //              // Result Result if exists\r
154 //              if(getter.result==null) {\r
155 //                      return Result.err(Status.ERR_NotFound, "No Cache or Lookup found on [%s]",dao.table());\r
156 //              }\r
157 //              return getter.result;\r
158         }\r
159 \r
160         // Slight Improved performance available when String and Obj versions are known. \r
161         public Result<List<DATA>> read(final String key, final TRANS trans, final Object ... objs) {\r
162                 DAOGetter getter = new DAOGetter(trans,dao,objs); \r
163                 return get(trans, key, getter);\r
164 //              if(ld!=null) {\r
165 //                      return Result.ok(ld);//.emptyList(ld.isEmpty());\r
166 //              }\r
167 //              // Result Result if exists\r
168 //              if(getter.result==null) {\r
169 //                      return Result.err(Status.ERR_NotFound, "No Cache or Lookup found on [%s]",dao.table());\r
170 //              }\r
171 //              return getter.result;\r
172         }\r
173         \r
174         @Override\r
175         public Result<List<DATA>> read(TRANS trans, DATA data) {\r
176                 return read(trans,dao.keyFrom(data));\r
177         }\r
178         public Result<Void> update(TRANS trans, DATA data) {\r
179                 Result<Void> d = dao.update(trans, data);\r
180                 if(d.status==Status.OK) {\r
181                     add(data);\r
182                 } else {\r
183                         trans.error().log(d.errorString());\r
184                 }\r
185                 return d;\r
186         }\r
187 \r
188         public Result<Void> delete(TRANS trans, DATA data, boolean reread) {\r
189                 if(reread) { // If reread, get from Cache, if possible, not DB exclusively\r
190                         Result<List<DATA>> rd = read(trans,data);\r
191                         if(rd.notOK()) {\r
192                             return Result.err(rd);\r
193                         } else {\r
194                                 trans.error().log(rd.errorString());\r
195                         }\r
196                         if(rd.isEmpty()) {\r
197                                 data.invalidate(this);\r
198                                 return Result.err(Status.ERR_NotFound,"Not Found");\r
199                         }\r
200                         data = rd.value.get(0);\r
201                 }\r
202                 Result<Void> rv=dao.delete(trans, data, false);\r
203                 data.invalidate(this);\r
204                 return rv;\r
205         }\r
206         \r
207         @Override\r
208         public void close(TRANS trans) {\r
209                 if(dao!=null) {\r
210                     dao.close(trans);\r
211                 }\r
212         }\r
213         \r
214 \r
215         @Override\r
216         public String table() {\r
217                 return dao.table();\r
218         }\r
219         \r
220         public D dao() {\r
221                 return dao;\r
222         }\r
223         \r
224         public void invalidate(TRANS trans, DATA data) {\r
225         if(info.touch(trans, dao.table(),data.invalidate(this)).notOK()) {\r
226             trans.error().log("Cannot touch CacheInfo for Role");\r
227         }\r
228         }\r
229 }\r