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 if (logger.isDebugEnabled()) {
148 logger.debug("Coming inside genCreateTableQuery method " + this.getKeyspaceName());
149 logger.debug("Coming inside genCreateTableQuery method " + this.getTableName());
152 String primaryKey = null;
153 String partitionKey = this.getPartitionKey();
154 String clusterKey = this.getClusteringKey();
155 String filteringKey = this.getFilteringKey();
156 if (filteringKey != null) {
157 clusterKey = clusterKey + "," + filteringKey;
159 primaryKey = this.getPrimaryKey(); // get primaryKey if available
161 PreparedQueryObject queryObject = new PreparedQueryObject();
162 // first read the information about the table fields
163 Map<String, String> fields = this.getFields();
164 if (fields == null) {
165 throw new MusicQueryException(
166 "Create Table Error: No fields in request", Status.BAD_REQUEST.getStatusCode());
168 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
170 for (Map.Entry<String, String> entry : fields.entrySet()) {
171 if (entry.getKey().equals("PRIMARY KEY")) {
172 primaryKey = entry.getValue(); // replaces primaryKey
173 primaryKey = primaryKey.trim();
175 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
176 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
179 if (counter != (fields.size() - 1) ) {
180 counter = counter + 1;
183 if((primaryKey != null) && (partitionKey == null)) {
184 primaryKey = primaryKey.trim();
185 int count1 = StringUtils.countMatches(primaryKey, ')');
186 int count2 = StringUtils.countMatches(primaryKey, '(');
187 if (count1 != count2) {
188 throw new MusicQueryException(
189 "Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey,
190 Status.BAD_REQUEST.getStatusCode());
193 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) {
194 if (primaryKey.contains(",") ) {
195 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
196 partitionKey=partitionKey.replaceAll("[\\(]+","");
197 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
198 clusterKey=clusterKey.replaceAll("[)]+", "");
200 partitionKey=primaryKey;
201 partitionKey=partitionKey.replaceAll("[\\)]+","");
202 partitionKey=partitionKey.replaceAll("[\\(]+","");
205 } else { // not null and has ) before the last char
206 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
207 partitionKey=partitionKey.replaceAll("[\\(]+","");
208 partitionKey = partitionKey.trim();
209 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
210 clusterKey=clusterKey.replaceAll("[\\(]+","");
211 clusterKey=clusterKey.replaceAll("[\\)]+","");
212 clusterKey = clusterKey.trim();
213 if (clusterKey.indexOf(',') == 0) {
214 clusterKey=clusterKey.substring(1);
216 clusterKey = clusterKey.trim();
217 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
220 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
221 && (partitionKey.equalsIgnoreCase(clusterKey) ||
222 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
223 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
224 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
225 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
226 + " primary key=" + primaryKey)
228 throw new MusicQueryException("Create Table primary key error: clusterKey(" + clusterKey
229 + ") equals/contains/overlaps partitionKey(" + partitionKey + ") of" + " primary key="
230 + primaryKey, Status.BAD_REQUEST.getStatusCode());
234 if (partitionKey.isEmpty() ) primaryKey="";
235 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
236 else primaryKey=" (" + partitionKey + ")," + clusterKey;
239 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
241 } else { // end of length > 0
243 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
244 && (partitionKey.equalsIgnoreCase(clusterKey) ||
245 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
246 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
247 /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
248 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
250 throw new MusicQueryException(
251 "Create Table primary key error: clusterKey(" + clusterKey
252 + ") equals/contains/overlaps partitionKey(" + partitionKey + ")",
253 Status.BAD_REQUEST.getStatusCode());
256 if (partitionKey.isEmpty() ) primaryKey="";
257 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
258 else primaryKey=" (" + partitionKey + ")," + clusterKey;
260 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
262 fieldsString.append(")");
264 } // end of last field check
267 // information about the name-value style properties
268 Map<String, Object> propertiesMap = this.getProperties();
269 StringBuilder propertiesString = new StringBuilder();
270 if (propertiesMap != null) {
272 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
273 Object ot = entry.getValue();
274 String value = ot + "";
275 if (ot instanceof String) {
276 value = "'" + value + "'";
277 } else if (ot instanceof Map) {
278 @SuppressWarnings("unchecked")
279 Map<String, Object> otMap = (Map<String, Object>) ot;
281 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
282 } catch (Exception e) {
283 throw new MusicQueryException(e.getMessage(),
284 Status.BAD_REQUEST.getStatusCode());
288 propertiesString.append(entry.getKey() + "=" + value + "");
289 if (counter != propertiesMap.size() - 1)
290 propertiesString.append(" AND ");
292 counter = counter + 1;
296 String clusteringOrder = this.getClusteringOrder();
298 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
299 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
301 for (int i = 0; i < arrayClusterOrder.length; i++) {
302 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
303 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
306 /*return response.status(Status.BAD_REQUEST)
307 .entity(new JsonResponse(ResultType.FAILURE)
308 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
311 throw new MusicQueryException(
312 "createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"
313 + clusteringOrder + ".",
314 Status.BAD_REQUEST.getStatusCode());
316 // add validation for column names in cluster key
319 if (!(clusterKey.isEmpty())) {
320 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
321 //cjc check if propertiesString.length() >0 instead propertiesMap
322 if (propertiesMap != null) {
323 propertiesString.append(" AND "+ clusteringOrder);
325 propertiesString.append(clusteringOrder);
328 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
332 queryObject.appendQueryString(
333 "CREATE TABLE " + this.getKeyspaceName() + "." + this.getTableName() + " " + fieldsString);
336 if (propertiesString != null && propertiesString.length()>0 )
337 queryObject.appendQueryString(" WITH " + propertiesString);
338 queryObject.appendQueryString(";");
347 public PreparedQueryObject genCreateShadowLockingTableQuery() {
348 if (logger.isDebugEnabled()) {
349 logger.debug("Coming inside genCreateShadowLockingTableQuery method " + this.getKeyspaceName());
350 logger.debug("Coming inside genCreateShadowLockingTableQuery method " + this.getTableName());
353 String tableName = "unsyncedKeys_" + this.getTableName();
354 String tabQuery = "CREATE TABLE IF NOT EXISTS " + this.getKeyspaceName() + "." + tableName
355 + " ( key text,PRIMARY KEY (key) );";
356 PreparedQueryObject queryObject = new PreparedQueryObject();
357 queryObject.appendQueryString(tabQuery);
365 * @return PreparedQueryObject
367 public PreparedQueryObject genDropTableQuery() {
368 if (logger.isDebugEnabled()) {
369 logger.debug("Coming inside genDropTableQuery method " + this.getKeyspaceName());
370 logger.debug("Coming inside genDropTableQuery method " + this.getTableName());
373 PreparedQueryObject query = new PreparedQueryObject();
374 query.appendQueryString("DROP TABLE " + this.getKeyspaceName() + "." + this.getTableName() + ";");
375 logger.info("Delete Query ::::: " + query.getQuery());