001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie.store; 020 021import java.sql.Timestamp; 022import java.util.Date; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.oozie.ErrorCode; 027import org.apache.oozie.client.OozieClient; 028import org.apache.oozie.executor.jpa.JPAExecutorException; 029import org.apache.oozie.util.DateUtils; 030import org.apache.oozie.util.XLog; 031 032public class StoreStatusFilter { 033 public static final String coordSeletStr = "Select w.id, w.appName, w.statusStr, w.user, w.group, w.startTimestamp, " + 034 "w.endTimestamp, w.appPath, w.concurrency, w.frequency, w.lastActionTimestamp, w.nextMaterializedTimestamp, " + 035 "w.createdTimestamp, w.timeUnitStr, w.timeZone, w.timeOut, w.bundleId from CoordinatorJobBean w"; 036 037 public static final String coordCountStr = "Select count(w) from CoordinatorJobBean w"; 038 039 public static final String wfSeletStr = "Select w.id, w.appName, w.statusStr, w.run, w.user, w.group, w.createdTimestamp, " + 040 "w.startTimestamp, w.lastModifiedTimestamp, w.endTimestamp from WorkflowJobBean w"; 041 042 public static final String wfCountStr = "Select count(w) from WorkflowJobBean w"; 043 044 public static final String bundleSeletStr = "Select w.id, w.appName, w.appPath, w.conf, w.statusStr, w.kickoffTimestamp, " + 045 "w.startTimestamp, w.endTimestamp, w.pauseTimestamp, w.createdTimestamp, w.user, w.group, w.timeUnitStr, " + 046 "w.timeOut from BundleJobBean w"; 047 048 public static final String bundleCountStr = "Select count(w) from BundleJobBean w"; 049 050 public static final String TIME_FORMAT = " Specify time either in UTC format (yyyy-MM-dd'T'HH:mm'Z') or " + 051 "a offset value in days/hours/minutes e.g. (-2d/h/m) from the current time."; 052 053 054 public static void filter(Map<String, List<String>> filter, List<String> orArray, List<String> colArray, 055 List<Object> valArray, StringBuilder sb, String seletStr, String countStr) throws JPAExecutorException { 056 boolean isStatus = false; 057 boolean isAppName = false; 058 boolean isUser = false; 059 boolean isEnabled = false; 060 boolean isFrequency = false; 061 boolean isId = false; 062 boolean isUnit = false; 063 064 int index = 0; 065 066 for (Map.Entry<String, List<String>> entry : filter.entrySet()) { 067 String colName = null; 068 String colVar = null; 069 if (entry.getKey().equals(OozieClient.FILTER_GROUP)) { 070 XLog.getLog(StoreStatusFilter.class).warn("Filter by 'group' is not supported anymore"); 071 } 072 else { 073 if (entry.getKey().equals(OozieClient.FILTER_STATUS)) { 074 List<String> values = filter.get(OozieClient.FILTER_STATUS); 075 colName = "status"; 076 for (int i = 0; i < values.size(); i++) { 077 colVar = "status"; 078 colVar = colVar + index; 079 if (!isEnabled && !isStatus) { 080 sb.append(seletStr).append(" where w.statusStr IN (:status" + index); 081 isStatus = true; 082 isEnabled = true; 083 } 084 else { 085 if (isEnabled && !isStatus) { 086 sb.append(" and w.statusStr IN (:status" + index); 087 isStatus = true; 088 } 089 else { 090 if (isStatus) { 091 sb.append(", :status" + index); 092 } 093 } 094 } 095 if (i == values.size() - 1) { 096 sb.append(")"); 097 } 098 index++; 099 valArray.add(values.get(i)); 100 orArray.add(colName); 101 colArray.add(colVar); 102 } 103 } 104 else { 105 if (entry.getKey().equals(OozieClient.FILTER_NAME)) { 106 List<String> values = filter.get(OozieClient.FILTER_NAME); 107 colName = "appName"; 108 for (int i = 0; i < values.size(); i++) { 109 colVar = "appName"; 110 colVar = colVar + index; 111 if (!isEnabled && !isAppName) { 112 sb.append(seletStr).append(" where w.appName IN (:appName" + index); 113 isAppName = true; 114 isEnabled = true; 115 } 116 else { 117 if (isEnabled && !isAppName) { 118 sb.append(" and w.appName IN (:appName" + index); 119 isAppName = true; 120 } 121 else { 122 if (isAppName) { 123 sb.append(", :appName" + index); 124 } 125 } 126 } 127 if (i == values.size() - 1) { 128 sb.append(")"); 129 } 130 index++; 131 valArray.add(values.get(i)); 132 orArray.add(colName); 133 colArray.add(colVar); 134 } 135 } 136 else { 137 if (entry.getKey().equals(OozieClient.FILTER_USER)) { 138 List<String> values = filter.get(OozieClient.FILTER_USER); 139 colName = "user"; 140 for (int i = 0; i < values.size(); i++) { 141 colVar = "user"; 142 colVar = colVar + index; 143 if (!isEnabled && !isUser) { 144 sb.append(seletStr).append(" where w.user IN (:user" + index); 145 isUser = true; 146 isEnabled = true; 147 } 148 else { 149 if (isEnabled && !isUser) { 150 sb.append(" and w.user IN (:user" + index); 151 isUser = true; 152 } 153 else { 154 if (isUser) { 155 sb.append(", :user" + index); 156 } 157 } 158 } 159 if (i == values.size() - 1) { 160 sb.append(")"); 161 } 162 index++; 163 valArray.add(values.get(i)); 164 orArray.add(colName); 165 colArray.add(colVar); 166 } 167 } 168 else if (entry.getKey().equals(OozieClient.FILTER_FREQUENCY)) { 169 List<String> values = filter.get(OozieClient.FILTER_FREQUENCY); 170 colName = "frequency"; 171 for (int i = 0; i < values.size(); i++) { 172 colVar = "frequency"; 173 colVar = colVar + index; 174 if (!isEnabled && !isFrequency) { 175 sb.append(seletStr).append(" where w.frequency IN (:frequency" + index); 176 isFrequency = true; 177 isEnabled = true; 178 } 179 else { 180 if (isEnabled && !isFrequency) { 181 sb.append(" and w.frequency IN (:frequency" + index); 182 isFrequency = true; 183 } 184 else { 185 if (isFrequency) { 186 sb.append(", :frequency" + index); 187 } 188 } 189 } 190 if (i == values.size() - 1) { 191 sb.append(")"); 192 } 193 index++; 194 valArray.add(values.get(i)); 195 orArray.add(colName); 196 colArray.add(colVar); 197 } 198 } 199 else if (entry.getKey().equals(OozieClient.FILTER_ID)) { 200 List<String> values = filter.get(OozieClient.FILTER_ID); 201 colName = "id"; 202 for (int i = 0; i < values.size(); i++) { 203 colVar = "id"; 204 colVar = colVar + index; 205 if (!isEnabled && !isId) { 206 sb.append(seletStr).append(" where w.id IN (:id" + index); 207 isId = true; 208 isEnabled = true; 209 } 210 else { 211 if (isEnabled && !isId) { 212 sb.append(" and w.id IN (:id" + index); 213 isId = true; 214 } 215 else { 216 if (isId) { 217 sb.append(", :id" + index); 218 } 219 } 220 } 221 if (i == values.size() - 1) { 222 sb.append(")"); 223 } 224 index++; 225 valArray.add(values.get(i)); 226 orArray.add(colName); 227 colArray.add(colVar); 228 } 229 } 230 // Filter map has time unit filter specified 231 else if (entry.getKey().equals(OozieClient.FILTER_UNIT)) { 232 List<String> values = filter.get(OozieClient.FILTER_UNIT); 233 colName = "timeUnitStr"; 234 for (int i = 0; i < values.size(); ++i) { 235 colVar = colName + index; 236 // This unit filter value is the first condition to be added to the where clause of 237 // query 238 if (!isEnabled && !isUnit) { 239 sb.append(seletStr).append(" where w.timeUnitStr IN (:timeUnitStr" + index); 240 isUnit = true; 241 isEnabled = true; 242 } else { 243 // Unit filter is neither the first nor the last condition to be added to the where 244 // clause of query 245 if (isEnabled && !isUnit) { 246 sb.append(" and w.timeUnitStr IN (:timeUnitStr" + index); 247 isUnit = true; 248 } else { 249 if (isUnit) { 250 sb.append(", :timeUnitStr" + index); 251 } 252 } 253 } 254 // This unit filter value is the last condition to be added to the where clause of query 255 if (i == values.size() - 1) { 256 sb.append(")"); 257 } 258 ++index; 259 valArray.add(values.get(i)); 260 orArray.add(colName); 261 colArray.add(colVar); 262 } 263 } 264 else if (entry.getKey().equalsIgnoreCase(OozieClient.FILTER_CREATED_TIME_START)) { 265 List<String> values = filter.get(OozieClient.FILTER_CREATED_TIME_START); 266 colName = "createdTimestampStart"; 267 if (values.size() > 1) { 268 throw new JPAExecutorException(ErrorCode.E0302, 269 "cannot specify multiple startcreatedtime"); 270 } 271 colVar = colName; 272 colVar = colVar + index; 273 if (!isEnabled) { 274 sb.append(seletStr).append(" where w.createdTimestamp >= :" + colVar); 275 isEnabled = true; 276 } 277 else { 278 sb.append(" and w.createdTimestamp >= :" + colVar); 279 } 280 index++; 281 Date createdTime = null; 282 try { 283 createdTime = parseCreatedTimeString(values.get(0)); 284 } 285 catch (Exception e) { 286 throw new JPAExecutorException(ErrorCode.E0302, e.getMessage()); 287 } 288 Timestamp createdTimeStamp = new Timestamp(createdTime.getTime()); 289 valArray.add(createdTimeStamp); 290 orArray.add(colName); 291 colArray.add(colVar); 292 293 } 294 else if (entry.getKey().equalsIgnoreCase(OozieClient.FILTER_CREATED_TIME_END)) { 295 List<String> values = filter.get(OozieClient.FILTER_CREATED_TIME_END); 296 colName = "createdTimestampEnd"; 297 if (values.size() > 1) { 298 throw new JPAExecutorException(ErrorCode.E0302, 299 "cannot specify multiple endcreatedtime"); 300 } 301 colVar = colName; 302 colVar = colVar + index; 303 if (!isEnabled) { 304 sb.append(seletStr).append(" where w.createdTimestamp <= :" + colVar); 305 isEnabled = true; 306 } 307 else { 308 sb.append(" and w.createdTimestamp <= :" + colVar); 309 } 310 index++; 311 Date createdTime = null; 312 try { 313 createdTime = parseCreatedTimeString(values.get(0)); 314 } 315 catch (Exception e) { 316 throw new JPAExecutorException(ErrorCode.E0302, e.getMessage()); 317 } 318 Timestamp createdTimeStamp = new Timestamp(createdTime.getTime()); 319 valArray.add(createdTimeStamp); 320 orArray.add(colName); 321 colArray.add(colVar); 322 } 323 } 324 } 325 } 326 } 327 } 328 329 private static Date parseCreatedTimeString(String time) throws Exception{ 330 Date createdTime = null; 331 int offset = 0; 332 if (Character.isLetter(time.charAt(time.length() - 1))) { 333 switch (time.charAt(time.length() - 1)) { 334 case 'd': 335 offset = Integer.parseInt(time.substring(0, time.length() - 1)); 336 if(offset > 0) { 337 throw new IllegalArgumentException("offset must be minus from currentTime."); 338 } 339 createdTime = org.apache.commons.lang.time.DateUtils.addDays(new Date(), offset); 340 break; 341 case 'h': 342 offset = Integer.parseInt(time.substring(0, time.length() - 1)); 343 if(offset > 0) { 344 throw new IllegalArgumentException("offset must be minus from currentTime."); 345 } 346 createdTime = org.apache.commons.lang.time.DateUtils.addHours(new Date(), offset); 347 break; 348 case 'm': 349 offset = Integer.parseInt(time.substring(0, time.length() - 1)); 350 if(offset > 0) { 351 throw new IllegalArgumentException("offset must be minus from currentTime."); 352 } 353 createdTime = org.apache.commons.lang.time.DateUtils.addMinutes(new Date(), offset); 354 break; 355 case 'Z': 356 createdTime = DateUtils.parseDateUTC(time); 357 break; 358 default: 359 throw new IllegalArgumentException("Unsupported time format: " + time + TIME_FORMAT); 360 } 361 } else { 362 throw new IllegalArgumentException("The format of time is wrong: " + time + TIME_FORMAT); 363 } 364 return createdTime; 365 } 366 367 public static String getSortBy(Map<String, List<String>> filter, String sortByStr) throws JPAExecutorException { 368 if (filter.containsKey(OozieClient.FILTER_SORT_BY)) { 369 List<String> values = filter.get(OozieClient.FILTER_SORT_BY); 370 if (values.size() > 1) { 371 throw new JPAExecutorException(ErrorCode.E0302, 372 "cannot specify multiple sortby parameter"); 373 } 374 String value = values.get(0); 375 for (OozieClient.SORT_BY sortBy : OozieClient.SORT_BY.values()) { 376 if (sortBy.toString().equalsIgnoreCase(value)) { 377 value = sortBy.getFullname(); 378 sortByStr = " order by w.".concat(value).concat(" desc "); 379 break; 380 } 381 } 382 } 383 return sortByStr; 384 } 385}