Remove zookeeper reference
[music.git] / src / main / java / org / onap / music / rest / RestMusicQAPI.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
4  * ===================================================================
5  *  Copyright (c) 2017 AT&T Intellectual Property
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  * 
19  * ============LICENSE_END=============================================
20  * ====================================================================
21  */
22
23 package org.onap.music.rest;
24
25 import java.util.HashMap;
26 import java.util.Map;
27 import javax.ws.rs.Consumes;
28 import javax.ws.rs.DELETE;
29 import javax.ws.rs.GET;
30 import javax.ws.rs.HeaderParam;
31 import javax.ws.rs.POST;
32 import javax.ws.rs.PUT;
33 import javax.ws.rs.Path;
34 import javax.ws.rs.PathParam;
35 import javax.ws.rs.Produces;
36 import javax.ws.rs.core.Context;
37 import javax.ws.rs.core.MediaType;
38 import javax.ws.rs.core.UriInfo;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.Response.ResponseBuilder;
41 import javax.ws.rs.core.Response.Status;
42 import org.onap.music.datastore.jsonobjects.JsonDelete;
43 import org.onap.music.datastore.jsonobjects.JsonInsert;
44 import org.onap.music.datastore.jsonobjects.JsonTable;
45 import org.onap.music.datastore.jsonobjects.JsonUpdate;
46 import org.onap.music.eelf.logging.EELFLoggerDelegate;
47
48 import org.onap.music.eelf.logging.format.AppMessages;
49 import org.onap.music.eelf.logging.format.ErrorSeverity;
50 import org.onap.music.eelf.logging.format.ErrorTypes;
51 import org.apache.commons.lang3.StringUtils;
52 import org.onap.music.datastore.MusicDataStoreHandle;
53 import org.onap.music.datastore.PreparedQueryObject;
54 import com.datastax.driver.core.ResultSet;
55 import org.onap.music.exceptions.MusicServiceException;
56 import org.onap.music.main.MusicCore;
57 import org.onap.music.main.MusicUtil;
58 import org.onap.music.main.ResultType;
59 import org.onap.music.response.jsonobjects.JsonResponse;
60
61 import io.swagger.annotations.Api;
62 import io.swagger.annotations.ApiOperation;
63 import io.swagger.annotations.ApiParam;
64
65 // import io.swagger.models.Response;
66 // @Path("/v{version: [0-9]+}/priorityq/")
67 @Path("/v2/priorityq/")
68 @Api(value = "Q Api")
69 public class RestMusicQAPI {
70
71   private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicQAPI.class);
72   
73
74   /**
75    * 
76    * @param tableObj
77    * @param keyspace
78    * @param tablename
79    * @throws Exception
80    */
81  
82   @POST
83   @Path("/keyspaces/{keyspace}/{qname}") // qname same as tablename
84   @ApiOperation(value = "Create Q", response = String.class)
85   @Consumes(MediaType.APPLICATION_JSON)
86   @Produces(MediaType.APPLICATION_JSON)
87   public Response createQ(
88           @ApiParam(value = "Major Version", required = true) @PathParam("version") String version,
89           @ApiParam(value = "Minor Version",
90                   required = false) @HeaderParam("X-minorVersion") String minorVersion,
91           @ApiParam(value = "Patch Version",
92                   required = false) @HeaderParam("X-patchVersion") String patchVersion,
93           @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
94           @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns,
95           @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
96           JsonTable tableObj, 
97           @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace,
98           @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename)
99           throws Exception {
100     //logger.info(logger, "cjc before start in q 1** major version=" + version);
101
102     ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion);
103
104     Map<String, String> fields = tableObj.getFields();
105     if (fields == null) { // || (!fields.containsKey("order")) ){
106       logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
107               ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
108       return response.status(Status.BAD_REQUEST)
109               .entity(new JsonResponse(ResultType.FAILURE)
110                       .setError("CreateQ/Required table fields are empty or not set").toMap())
111               .build();
112     }
113
114     String primaryKey = tableObj.getPrimaryKey();
115     String partitionKey = tableObj.getPartitionKey();
116     String clusteringKey = tableObj.getClusteringKey();
117     String filteringKey = tableObj.getFilteringKey();
118     String clusteringOrder = tableObj.getClusteringOrder();
119
120     if(primaryKey == null) {
121         primaryKey = tableObj.getFields().get("PRIMARY KEY");
122     }
123
124     if ((primaryKey == null) && (partitionKey == null)) {
125         logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
126                 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
127         return response.status(Status.BAD_REQUEST)
128                 .entity(new JsonResponse(ResultType.FAILURE)
129                         .setError("CreateQ: Partition key cannot be empty").toMap())
130                 .build();
131       }
132
133     if ((primaryKey == null) && (clusteringKey == null)) {
134         logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
135                 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
136         return response.status(Status.BAD_REQUEST)
137                 .entity(new JsonResponse(ResultType.FAILURE)
138                         .setError("CreateQ: Clustering key cannot be empty").toMap())
139                 .build();
140       }
141
142     if (clusteringOrder == null) {
143         logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
144                 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
145         return response.status(Status.BAD_REQUEST)
146                 .entity(new JsonResponse(ResultType.FAILURE)
147                         .setError("CreateQ: Clustering Order cannot be empty").toMap())
148                 .build();
149       }
150
151     if ((primaryKey!=null) && (partitionKey == null)) {
152         primaryKey = primaryKey.trim();
153         int count1 = StringUtils.countMatches(primaryKey,')');
154         int count2 = StringUtils.countMatches(primaryKey,'(');
155         if (count1 != count2) {
156             return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
157                       .setError("CreateQ Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
158                       .toMap()).build();
159         }
160
161         if ( primaryKey.indexOf('(') == -1  || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) ==  primaryKey.length() ) )
162         {
163             if (primaryKey.contains(",") ) {
164                 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
165                 partitionKey=partitionKey.replaceAll("[\\(]+","");
166                 clusteringKey=primaryKey.substring(primaryKey.indexOf(',')+1);  // make sure index
167                 clusteringKey=clusteringKey.replaceAll("[)]+", "");
168             } else {
169               partitionKey=primaryKey;
170               partitionKey=partitionKey.replaceAll("[\\)]+","");
171               partitionKey=partitionKey.replaceAll("[\\(]+","");
172               clusteringKey="";
173            }
174       } else {
175             partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
176             partitionKey=partitionKey.replaceAll("[\\(]+","");
177             partitionKey = partitionKey.trim();
178             clusteringKey= primaryKey.substring(primaryKey.indexOf(')'));
179             clusteringKey=clusteringKey.replaceAll("[\\(]+","");
180             clusteringKey=clusteringKey.replaceAll("[\\)]+","");
181             clusteringKey = clusteringKey.trim();
182             if (clusteringKey.indexOf(',') == 0) clusteringKey=clusteringKey.substring(1);
183             clusteringKey = clusteringKey.trim();
184             if (clusteringKey.equals(",") ) clusteringKey=""; // print error if needed    ( ... ),)
185          }
186     }
187
188     if (partitionKey.trim().isEmpty()) {
189         logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
190                 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
191         return response.status(Status.BAD_REQUEST)
192                 .entity(new JsonResponse(ResultType.FAILURE)
193                         .setError("CreateQ: Partition key cannot be empty").toMap())
194                 .build();
195     }
196
197     if (clusteringKey.trim().isEmpty()) {
198         logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
199                 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
200         return response.status(Status.BAD_REQUEST)
201                 .entity(new JsonResponse(ResultType.FAILURE)
202                         .setError("CreateQ: Clustering key cannot be empty").toMap())
203                 .build();
204     }
205
206     if((filteringKey != null) && (filteringKey.equalsIgnoreCase(partitionKey))) {
207         logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
208                 ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
209         return response.status(Status.BAD_REQUEST)
210                 .entity(new JsonResponse(ResultType.FAILURE)
211                         .setError("CreateQ: Filtering key cannot be same as Partition Key").toMap())
212                 .build();
213     }
214
215     return new RestMusicDataAPI().createTable(version, minorVersion, patchVersion, aid, ns, authorization, tableObj, keyspace, tablename);
216   }
217
218   /**
219    * 
220    * @param insObj
221    * @param keyspace
222    * @param tablename
223    * @throws Exception
224    */
225   @POST
226   @Path("/keyspaces/{keyspace}/{qname}/rows")
227   @ApiOperation(value = "", response = Void.class)
228   @Consumes(MediaType.APPLICATION_JSON)
229   @Produces(MediaType.APPLICATION_JSON)
230   // public Map<String, Object> insertIntoQ(
231   public Response insertIntoQ(
232           @ApiParam(value = "Major Version", required = true) @PathParam("version") String version,
233           @ApiParam(value = "Minor Version",
234                   required = false) @HeaderParam("X-minorVersion") String minorVersion,
235           @ApiParam(value = "Patch Version",
236                   required = false) @HeaderParam("X-patchVersion") String patchVersion,
237           @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
238           @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns,
239           @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
240           JsonInsert insObj,
241           @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace,
242           @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename)
243           throws Exception {
244     ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion);
245     if (insObj.getValues().isEmpty()) {
246       logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
247               ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
248       return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
249               .setError("Required HTTP Request body is missing.").toMap()).build();
250     }
251     return new RestMusicDataAPI().insertIntoTable(version, minorVersion, patchVersion, aid, ns,
252             authorization, insObj, keyspace, tablename);
253   }
254
255   /**
256    * 
257    * @param updateObj
258    * @param keyspace
259    * @param tablename
260    * @param info
261    * @return
262    * @throws Exception
263    */
264   @PUT
265   @Path("/keyspaces/{keyspace}/{qname}/rows")
266   @ApiOperation(value = "updateQ", response = String.class)
267   @Consumes(MediaType.APPLICATION_JSON)
268   @Produces(MediaType.APPLICATION_JSON)
269   public Response updateQ(
270           @ApiParam(value = "Major Version", required = true) @PathParam("version") String version,
271           @ApiParam(value = "Minor Version",
272                   required = false) @HeaderParam("X-minorVersion") String minorVersion,
273           @ApiParam(value = "Patch Version",
274                   required = false) @HeaderParam("X-patchVersion") String patchVersion,
275           @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
276           @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns,
277           @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
278           JsonUpdate updateObj,
279           @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace,
280           @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename,
281           @Context UriInfo info) throws Exception {
282
283     ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion);
284     if (updateObj.getValues().isEmpty()) {
285       logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
286               ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
287       return response.status(Status.BAD_REQUEST)
288               .entity(new JsonResponse(ResultType.FAILURE).setError(
289                       "Required HTTP Request body is missing. JsonUpdate updateObj.getValues() is empty. ")
290                       .toMap())
291               .build();
292
293  
294     }
295     return new RestMusicDataAPI().updateTable(version, minorVersion, patchVersion, aid, ns, 
296             authorization,updateObj, keyspace, tablename, info);
297   }
298
299   /**
300    * 
301    * @param delObj
302    * @param keyspace
303    * @param tablename
304    * @param info
305    * 
306    * @return
307    * @throws Exception
308    */
309
310   @DELETE
311   @Path("/keyspaces/{keyspace}/{qname}/rows")
312   @ApiOperation(value = "deleteQ", response = String.class)
313   @Consumes(MediaType.APPLICATION_JSON)
314   @Produces(MediaType.APPLICATION_JSON)
315   public Response deleteFromQ(
316           @ApiParam(value = "Major Version", required = true) @PathParam("version") String version,
317           @ApiParam(value = "Minor Version",
318                   required = false) @HeaderParam("X-minorVersion") String minorVersion,
319           @ApiParam(value = "Patch Version",
320                   required = false) @HeaderParam("X-patchVersion") String patchVersion,
321           @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
322           @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns,
323           @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
324           JsonDelete delObj,
325           @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace,
326           @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename,
327           @Context UriInfo info) throws Exception {
328     // added checking as per RestMusicDataAPI
329     ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion);
330     if (delObj == null) {
331       logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.MISSINGDATA,
332               ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
333       return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
334               .setError("deleteFromQ JsonDelete delObjis empty").toMap()).build();
335     }
336
337     return new RestMusicDataAPI().deleteFromTable(version, minorVersion, patchVersion, aid, ns,
338             authorization, delObj, keyspace, tablename, info);
339   }
340
341   /**
342    * 
343    * @param keyspace
344    * @param tablename
345    * @param info
346    * @return
347    * @throws Exception
348    */
349   @GET
350   @Path("/keyspaces/{keyspace}/{qname}/peek")
351   @ApiOperation(value = "", response = Map.class)
352   @Produces(MediaType.APPLICATION_JSON)
353   //public Map<String, HashMap<String, Object>> peek(
354   public Response peek(
355           @ApiParam(value = "Major Version", required = true) @PathParam("version") String version,
356           @ApiParam(value = "Minor Version",
357                   required = false) @HeaderParam("X-minorVersion") String minorVersion,
358           @ApiParam(value = "Patch Version",
359                   required = false) @HeaderParam("X-patchVersion") String patchVersion,
360           @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
361           @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns,
362           @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
363           @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace,
364           @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename,
365           @Context UriInfo info) throws Exception {
366     int limit =1; //peek must return just the top row
367     Map<String ,String> auth = new HashMap<>();
368     String userId =auth.get(MusicUtil.USERID);
369     String password =auth.get(MusicUtil.PASSWORD);  
370     ResponseBuilder response = MusicUtil.buildVersionResponse(version, minorVersion, patchVersion);
371    
372     PreparedQueryObject queryObject = new PreparedQueryObject();
373     if (info.getQueryParameters() == null ) //|| info.getQueryParameters().isEmpty())
374       queryObject.appendQueryString(
375               "SELECT *  FROM " + keyspace + "." + tablename + " LIMIT " + limit + ";");
376     else {
377
378       try {
379         queryObject = new RestMusicDataAPI().selectSpecificQuery(keyspace, tablename, info, limit);
380       } catch (MusicServiceException ex) {
381         logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.UNKNOWNERROR,
382                 ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
383         return response.status(Status.BAD_REQUEST)
384                 .entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap())
385                 .build();
386       }
387     }
388
389     try {
390       ResultSet results = MusicCore.get(queryObject);
391       return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS)
392               .setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
393     } catch (MusicServiceException ex) {
394       logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.UNKNOWNERROR,
395               ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR);
396       return response.status(Status.BAD_REQUEST)
397               .entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap())
398               .build();
399     }
400   }
401
402   /**
403    * 
404    *
405    * @param keyspace
406    * @param tablename
407    * @param info
408    * @return
409    * @throws Exception
410    */
411   @GET
412   @Path("/keyspaces/{keyspace}/{qname}/filter")
413   @ApiOperation(value = "filter", response = Map.class)
414   @Produces(MediaType.APPLICATION_JSON)
415   // public Map<String, HashMap<String, Object>> filter(
416   public Response filter(
417       @ApiParam(value = "Major Version", required = true) @PathParam("version") String version,
418       @ApiParam(value = "Minor Version", required = false) @HeaderParam("X-minorVersion") String minorVersion,
419       @ApiParam(value = "Patch Version", required = false) @HeaderParam("X-patchVersion") String patchVersion,
420       @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
421       @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns,
422       @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
423       @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace,
424       @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename,
425       @Context UriInfo info) throws Exception {
426     return new RestMusicDataAPI().select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info);// , limit)
427     
428   }
429
430   /**
431    * 
432    * @param tabObj
433    * @param keyspace
434    * @param tablename
435    * @throws Exception
436    */
437   @DELETE
438   @ApiOperation(value = "DropQ", response = String.class)
439   @Path("/keyspaces/{keyspace}/{qname}")
440   @Produces(MediaType.APPLICATION_JSON)
441   public Response dropQ(
442           @ApiParam(value = "Major Version", required = true) @PathParam("version") String version,
443           @ApiParam(value = "Minor Version",
444                   required = false) @HeaderParam("X-minorVersion") String minorVersion,
445           @ApiParam(value = "Patch Version",
446                   required = false) @HeaderParam("X-patchVersion") String patchVersion,
447           @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
448           @ApiParam(value = "Application namespace", required = true) @HeaderParam("ns") String ns,
449           @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
450           @ApiParam(value = "Key Space", required = true) @PathParam("keyspace") String keyspace,
451           @ApiParam(value = "Table Name", required = true) @PathParam("qname") String tablename)
452           throws Exception {
453
454     return new RestMusicDataAPI().dropTable(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename);
455   }
456 }