1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\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
11 * * http://www.apache.org/licenses/LICENSE-2.0
\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
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
23 package org.onap.aaf.dao;
\r
25 import java.util.ArrayList;
\r
26 import java.util.List;
\r
28 import org.onap.aaf.authz.layer.Result;
\r
29 import org.onap.aaf.dao.aaf.cass.Status;
\r
31 import org.onap.aaf.inno.env.Trans;
\r
36 * Cache the response of "get" of any DAO.
\r
38 * For simplicity's sake, at this time, we only do this for single Object keys
\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
47 private final D dao;
\r
49 public CachedDAO(D dao, CIDAO<TRANS> info, int segsize) {
\r
50 super(info, dao.table(), segsize);
\r
52 // Instantiate a new Cache per DAO name (so separate instances use the same cache)
\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
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
66 public void add(DATA data) {
\r
67 String key = keyFromObjs(dao.keyFrom(data));
\r
68 List<DATA> list = new ArrayList<DATA>();
\r
70 super.add(key,list);
\r
73 // public void invalidate(TRANS trans, Object ... objs) {
\r
74 // TimeTaken tt = trans.start(dirty_str, Env.SUB);
\r
76 // super.invalidate(keyFromObjs(objs));
\r
82 public static String keyFromObjs(Object ... objs) {
\r
84 if(objs.length==1 && objs[0] instanceof String) {
\r
85 key = (String)objs[0];
\r
87 StringBuilder sb = new StringBuilder();
\r
88 boolean first = true;
\r
89 for(Object o : objs) {
\r
96 sb.append(o.toString());
\r
99 key = sb.toString();
\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
109 trans.error().log(d.errorString());
\r
111 invalidate(trans,data);
\r
115 protected class DAOGetter implements Getter<DATA> {
\r
116 protected TRANS trans;
\r
117 protected Object objs[];
\r
119 public Result<List<DATA>> result;
\r
121 public DAOGetter(TRANS trans, D dao, Object ... objs) {
\r
122 this.trans = trans;
\r
128 * Separated into single call for easy overloading
\r
131 public Result<List<DATA>> call() {
\r
132 return dao.read(trans, objs);
\r
136 public final Result<List<DATA>> get() {
\r
138 // if(result.isOKhasData()) { // Note, given above logic, could exist, but stale
\r
139 // return result.value;
\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
151 // return Result.ok(ld);//.emptyList(ld.isEmpty());
\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
157 // return getter.result;
\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
165 // return Result.ok(ld);//.emptyList(ld.isEmpty());
\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
171 // return getter.result;
\r
175 public Result<List<DATA>> read(TRANS trans, DATA data) {
\r
176 return read(trans,dao.keyFrom(data));
\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
183 trans.error().log(d.errorString());
\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
192 return Result.err(rd);
\r
194 trans.error().log(rd.errorString());
\r
197 data.invalidate(this);
\r
198 return Result.err(Status.ERR_NotFound,"Not Found");
\r
200 data = rd.value.get(0);
\r
202 Result<Void> rv=dao.delete(trans, data, false);
\r
203 data.invalidate(this);
\r
208 public void close(TRANS trans) {
\r
216 public String table() {
\r
217 return dao.table();
\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