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