2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Modifications Copyright (C) 2019 IBM
8 * ===================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ============LICENSE_END=============================================
22 * ====================================================================
25 package org.onap.music.datastore.jsonobjects;
29 import javax.ws.rs.core.Response.Status;
31 import org.apache.commons.lang3.StringUtils;
32 import org.onap.music.datastore.PreparedQueryObject;
33 import org.onap.music.eelf.logging.EELFLoggerDelegate;
34 import org.onap.music.exceptions.MusicQueryException;
35 import org.onap.music.main.MusicUtil;
37 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
39 import io.swagger.annotations.ApiModel;
40 import io.swagger.annotations.ApiModelProperty;
42 @ApiModel(value = "JsonTable", description = "Defines the Json for Creating a new Table.")
43 @JsonIgnoreProperties(ignoreUnknown = true)
44 public class JsonTable {
45 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonTable.class);
47 private String keyspaceName;
48 private String tableName;
50 private Map<String, String> fields;
51 private Map<String, Object> properties;
52 private String primaryKey;
53 private String partitionKey;
54 private String clusteringKey;
55 private String filteringKey;
56 private String clusteringOrder;
57 private Map<String, String> consistencyInfo;
59 @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic")
60 public Map<String, String> getConsistencyInfo() {
61 return consistencyInfo;
64 public void setConsistencyInfo(Map<String, String> consistencyInfo) {
65 this.consistencyInfo = consistencyInfo;
68 @ApiModelProperty(value = "Properties")
69 public Map<String, Object> getProperties() {
73 public void setProperties(Map<String, Object> properties) {
74 this.properties = properties;
77 @ApiModelProperty(value = "Fields")
78 public Map<String, String> getFields() {
82 public void setFields(Map<String, String> fields) {
86 @ApiModelProperty(value = "KeySpace Name")
87 public String getKeyspaceName() {
91 public void setKeyspaceName(String keyspaceName) {
92 this.keyspaceName = keyspaceName;
95 @ApiModelProperty(value = "Table Name")
96 public String getTableName() {
100 public void setTableName(String tableName) {
101 this.tableName = tableName;
104 @ApiModelProperty(value = "Clustering Order", notes = "")
105 public String getClusteringOrder() {
106 return clusteringOrder;
109 public void setClusteringOrder(String clusteringOrder) {
110 this.clusteringOrder = clusteringOrder;
113 @ApiModelProperty(value = "Primary Key")
114 public String getPrimaryKey() {
118 public void setPrimaryKey(String primaryKey) {
119 this.primaryKey = primaryKey;
122 public String getClusteringKey() {
123 return clusteringKey;
126 public void setClusteringKey(String clusteringKey) {
127 this.clusteringKey = clusteringKey;
130 public String getFilteringKey() {
134 public void setFilteringKey(String filteringKey) {
135 this.filteringKey = filteringKey;
138 public String getPartitionKey() {
142 public void setPartitionKey(String partitionKey) {
143 this.partitionKey = partitionKey;
146 public PreparedQueryObject genCreateTableQuery() throws MusicQueryException {
147 String primaryKey = null;
148 String partitionKey = this.getPartitionKey();
149 String clusterKey = this.getClusteringKey();
150 String filteringKey = this.getFilteringKey();
151 if (filteringKey != null) {
152 clusterKey = clusterKey + "," + filteringKey;
154 primaryKey = this.getPrimaryKey(); // get primaryKey if available
156 PreparedQueryObject queryObject = new PreparedQueryObject();
157 // first read the information about the table fields
158 Map<String, String> fields = this.getFields();
159 if (fields == null) {
160 throw new MusicQueryException(
161 "Create Table Error: No fields in request", Status.BAD_REQUEST.getStatusCode());
163 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
165 for (Map.Entry<String, String> entry : fields.entrySet()) {
166 if (entry.getKey().equals("PRIMARY KEY")) {
167 primaryKey = entry.getValue(); // replaces primaryKey
168 primaryKey = primaryKey.trim();
170 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
171 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
174 if (counter != (fields.size() - 1) ) {
175 counter = counter + 1;
178 if((primaryKey != null) && (partitionKey == null)) {
179 primaryKey = primaryKey.trim();
180 int count1 = StringUtils.countMatches(primaryKey, ')');
181 int count2 = StringUtils.countMatches(primaryKey, '(');
182 if (count1 != count2) {
183 throw new MusicQueryException(
184 "Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey,
185 Status.BAD_REQUEST.getStatusCode());
188 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) {
189 if (primaryKey.contains(",") ) {
190 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
191 partitionKey=partitionKey.replaceAll("[\\(]+","");
192 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
193 clusterKey=clusterKey.replaceAll("[)]+", "");
195 partitionKey=primaryKey;
196 partitionKey=partitionKey.replaceAll("[\\)]+","");
197 partitionKey=partitionKey.replaceAll("[\\(]+","");
200 } else { // not null and has ) before the last char
201 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
202 partitionKey=partitionKey.replaceAll("[\\(]+","");
203 partitionKey = partitionKey.trim();
204 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
205 clusterKey=clusterKey.replaceAll("[\\(]+","");
206 clusterKey=clusterKey.replaceAll("[\\)]+","");
207 clusterKey = clusterKey.trim();
208 if (clusterKey.indexOf(',') == 0) {
209 clusterKey=clusterKey.substring(1);
211 clusterKey = clusterKey.trim();
212 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
215 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
216 && (partitionKey.equalsIgnoreCase(clusterKey) ||
217 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
218 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
219 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
220 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
221 + " primary key=" + primaryKey)
223 throw new MusicQueryException("Create Table primary key error: clusterKey(" + clusterKey
224 + ") equals/contains/overlaps partitionKey(" + partitionKey + ") of" + " primary key="
225 + primaryKey, Status.BAD_REQUEST.getStatusCode());
229 if (partitionKey.isEmpty() ) primaryKey="";
230 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
231 else primaryKey=" (" + partitionKey + ")," + clusterKey;
234 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
236 } else { // end of length > 0
238 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
239 && (partitionKey.equalsIgnoreCase(clusterKey) ||
240 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
241 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
242 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
243 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
245 throw new MusicQueryException(
246 "Create Table primary key error: clusterKey(" + clusterKey
247 + ") equals/contains/overlaps partitionKey(" + partitionKey + ")",
248 Status.BAD_REQUEST.getStatusCode());
251 if (partitionKey.isEmpty() ) primaryKey="";
252 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
253 else primaryKey=" (" + partitionKey + ")," + clusterKey;
255 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
257 fieldsString.append(")");
259 } // end of last field check
262 // information about the name-value style properties
263 Map<String, Object> propertiesMap = this.getProperties();
264 StringBuilder propertiesString = new StringBuilder();
265 if (propertiesMap != null) {
267 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
268 Object ot = entry.getValue();
269 String value = ot + "";
270 if (ot instanceof String) {
271 value = "'" + value + "'";
272 } else if (ot instanceof Map) {
273 @SuppressWarnings("unchecked")
274 Map<String, Object> otMap = (Map<String, Object>) ot;
276 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
277 } catch (Exception e) {
278 throw new MusicQueryException(e.getMessage(),
279 Status.BAD_REQUEST.getStatusCode());
283 propertiesString.append(entry.getKey() + "=" + value + "");
284 if (counter != propertiesMap.size() - 1)
285 propertiesString.append(" AND ");
287 counter = counter + 1;
291 String clusteringOrder = this.getClusteringOrder();
293 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
294 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
296 for (int i = 0; i < arrayClusterOrder.length; i++) {
297 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
298 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
301 /*return response.status(Status.BAD_REQUEST)
302 .entity(new JsonResponse(ResultType.FAILURE)
303 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
306 throw new MusicQueryException(
307 "createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"
308 + clusteringOrder + ".",
309 Status.BAD_REQUEST.getStatusCode());
311 // add validation for column names in cluster key
314 if (!(clusterKey.isEmpty())) {
315 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
316 //cjc check if propertiesString.length() >0 instead propertiesMap
317 if (propertiesMap != null) {
318 propertiesString.append(" AND "+ clusteringOrder);
320 propertiesString.append(clusteringOrder);
323 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
327 queryObject.appendQueryString(
328 "CREATE TABLE " + this.getKeyspaceName() + "." + this.getTableName() + " " + fieldsString);
331 if (propertiesString != null && propertiesString.length()>0 )
332 queryObject.appendQueryString(" WITH " + propertiesString);
333 queryObject.appendQueryString(";");
341 * @return PreparedQueryObject
343 public PreparedQueryObject genDropTableQuery() {
344 PreparedQueryObject query = new PreparedQueryObject();
345 query.appendQueryString("DROP TABLE " + this.getKeyspaceName() + "." + this.getTableName() + ";");
346 logger.info("Delete Query ::::: " + query.getQuery());