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