e064ade3962dbe14871a1e5cbdbe4f493853631b
[aaf/authz.git] / auth / auth-core / src / main / java / org / onap / aaf / auth / layer / Result.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.layer;
23
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Set;
27
28
29 /**
30  * It would be nice if Java Enums were extensible, but they're not.
31  * 
32  * @author Jonathan
33  *
34  */
35 public class Result<RV> {
36     private static final String SUCCESS = "Success";
37     public static final String[] EMPTY_VARS = new String[0];
38
39     public final static int OK=0,
40                             ERR_Security                 = 1,
41                             ERR_Denied                     = 2,
42                             ERR_Policy                     = 3,
43                             ERR_BadData                 = 4,
44                             ERR_NotImplemented             = 5,
45                             ERR_NotFound                 = 6,
46                             ERR_ConflictAlreadyExists     = 7,
47                             ERR_ActionNotCompleted         = 8,
48                             ERR_Backend                    = 9,
49                             ERR_General                    = 20;
50                             
51     public RV value;
52     public final int status;
53     public final String details;
54     public final String[] variables;
55     
56     public Result(RV value, int status, String details, String[] variables) {
57         this.value = value;
58         if (value==null) {
59         specialCondition|=EMPTY_LIST;
60         }
61         this.status = status;
62         this.details = details;
63         if (variables==null) {
64             this.variables = EMPTY_VARS;
65         } else {
66             this.variables=variables;
67         }
68     }
69     
70     /**
71      * Create a Result class with "OK" status and "Success" for details
72      * 
73      * This is the easiest to use
74      * 
75      * @param value
76      * @param status
77      * @return
78      */
79     public static<R> Result<R> ok(R value) {
80         return new Result<R>(value,OK,SUCCESS,null);
81     }
82
83     /**
84      * Accept Arrays and mark as empty or not
85      * @param value
86      * @return
87      */
88     public static<R> Result<R[]> ok(R value[]) {
89         return new Result<R[]>(value,OK,SUCCESS,null).emptyList(value.length==0);
90     }
91
92     /**
93      * Accept Sets and mark as empty or not
94      * @param value
95      * @return
96      */
97     public static<R> Result<Set<R>> ok(Set<R> value) {
98         return new Result<Set<R>>(value,OK,SUCCESS,null).emptyList(value.size()==0);
99     }
100
101     /**
102      * Accept Lists and mark as empty or not
103      * @param value
104      * @return
105      */
106     public static<R> Result<List<R>> ok(List<R> value) {
107         return new Result<List<R>>(value,OK,SUCCESS,null).emptyList(value.size()==0);
108     }
109
110     /**
111      * Accept Collections and mark as empty or not
112      * @param value
113      * @return
114      */
115     public static<R> Result<Collection<R>> ok(Collection<R> value) {
116         return new Result<Collection<R>>(value,OK,SUCCESS,null).emptyList(value.size()==0);
117     }
118
119
120     /**
121      * Special Case for Void Type
122      * @return
123      */
124     public static Result<Void> ok() {
125         return new Result<Void>(null,OK,SUCCESS,null);
126     }
127
128     /**
129      * Create a Status (usually non OK, with a details statement 
130      * @param value
131      * @param status
132      * @param details
133      * @return
134      */
135 //    public static<R> Result<R> err(int status, String details) {
136 //        return new Result<R>(null,status,details,null);
137 //    }
138     
139     /**
140      * Create a Status (usually non OK, with a details statement and variables supported
141      * @param status
142      * @param details
143      * @param variables
144      * @return
145      */
146     public static<R> Result<R> err(int status, String details, String ... variables) {
147         return new Result<R>(null,status,details,variables);
148     }
149
150     /**
151      * Create Error from status and Details of previous Result (and not data)
152      * @param pdr
153      * @return
154      */
155     public static<R> Result<R> err(Result<?> pdr) {
156         return new Result<R>(null,pdr.status,pdr.details,pdr.variables);
157     }
158
159     /**
160      * Create General Error from Exception
161      * @param e
162      * @return
163      */
164     public static<R> Result<R> err(Exception e) {
165         return new Result<R>(null,ERR_General,e.getMessage(),EMPTY_VARS);
166     }
167
168     /**
169      * Create a Status (usually non OK, with a details statement 
170      * @param value
171      * @param status
172      * @param details
173      * @return
174      */
175     public static<R> Result<R> create(R value, int status, String details, String ... vars) {
176         return new Result<R>(value,status,details,vars);
177     }
178
179     /**
180      * Create a Status from a previous status' result/details 
181      * @param value
182      * @param status
183      * @param details
184      * @return
185      */
186     public static<R> Result<R> create(R value, Result<?> result) {
187         return new Result<R>(value,result.status,result.details,result.variables);
188     }
189
190     private static final int PARTIAL_CONTENT = 0x001;
191     private static final int EMPTY_LIST = 0x002;
192     
193     /**
194      * AAF Specific problems, etc 
195      * 
196      * @author Jonathan
197      *
198      */
199
200     /**
201      * specialCondition  is a bit field to enable multiple conditions, e.g. PARTIAL_CONTENT
202      */
203     private      int  specialCondition = 0;
204
205
206     /**
207      * Is result set only partial results, i.e. the DAO clipped the real result set to a smaller number.
208      * @return  true iff result returned PARTIAL_CONTENT
209      */
210     public boolean partialContent() {
211         return (specialCondition & PARTIAL_CONTENT) == PARTIAL_CONTENT;
212     }
213
214     /**
215      * Set fact that result set only returned partial results, i.e. the DAO clipped the real result set to a smaller number.
216      * @param hasPartialContent         set true iff result returned PARTIAL_CONTENT
217      * @return   this Result object, so you can chain calls, in builder style
218      */
219     public Result<RV> partialContent(boolean hasPartialContent) {
220         if (hasPartialContent) {
221         specialCondition |= PARTIAL_CONTENT;
222     } else {
223         specialCondition &= (~PARTIAL_CONTENT);
224     }
225         return this;
226     }
227
228     /**
229      * When Result is a List, you can check here to see if it's empty instead of looping
230      * 
231      * @return
232      */
233     public boolean isEmpty() {
234         return (specialCondition & EMPTY_LIST) == EMPTY_LIST;
235     }
236
237     /**
238      * A common occurrence is that data comes back, but list is empty.  If set, you can skip looking
239      * at list at the outset.
240      * 
241      * @param emptyList
242      * @return
243      */
244     public Result<RV> emptyList(boolean emptyList) {
245         if (emptyList) {
246             specialCondition |= EMPTY_LIST;
247         } else {
248             specialCondition &= (~EMPTY_LIST);
249         }
250         return this;
251     }
252
253     
254     /** 
255      * Convenience function.  Checks OK, and also if List is not Empty
256      * Not valid if Data is not a List
257      * @return
258      */
259     public boolean isOK() {
260         return status == OK;
261     }
262
263     /** 
264      * Convenience function.  Checks OK, and also if List is not Empty
265      * Not valid if Data is not a List
266      * @return
267      */
268     public boolean notOK() {
269         return status != OK;
270     }
271
272     /** 
273      * Convenience function.  Checks OK, and also if List is not Empty
274      * Not valid if Data is not a List
275      * @return
276      */
277     public boolean isOKhasData() {
278         return status == OK && (specialCondition & EMPTY_LIST) != EMPTY_LIST;
279     }
280
281
282     /** 
283      * Convenience function.  Checks OK, and also if List is not Empty
284      * Not valid if Data is not a List
285      * @return
286      */
287     public boolean notOKorIsEmpty() {
288         return status != OK || (specialCondition & EMPTY_LIST) == EMPTY_LIST;
289     }
290
291     @Override
292     public String toString() {
293         if (status==0) {
294             return details;
295         } else {
296             StringBuilder sb = new StringBuilder();
297             sb.append(status);
298             sb.append(':');
299             sb.append(String.format(details,((Object[])variables)));
300             if (isEmpty()) {
301                 sb.append("{empty}");
302             }
303             if (value!=null) {
304                 sb.append('-');
305                 sb.append(value.toString());
306             }
307             return sb.toString();
308         }
309     }
310     
311     public String errorString() {
312         StringBuilder sb = new StringBuilder();
313         switch(status) {
314             case 1: sb.append("Security"); break;
315             case 2: sb.append("Denied"); break;
316             case 3: sb.append("Policy"); break;
317             case 4: sb.append("BadData"); break;
318             case 5: sb.append("NotImplemented"); break;
319             case 6: sb.append("NotFound"); break;
320             case 7: sb.append("AlreadyExists"); break;
321             case 8: sb.append("ActionNotComplete"); break;
322             default: sb.append("Error");
323         }
324         sb.append(" - ");
325         sb.append(String.format(details, (Object[])variables));
326         return sb.toString();
327     }
328 }