| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.oozie.store; |
| |
| import java.sql.Timestamp; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.oozie.ErrorCode; |
| import org.apache.oozie.client.OozieClient; |
| import org.apache.oozie.executor.jpa.JPAExecutorException; |
| import org.apache.oozie.util.DateUtils; |
| import org.apache.oozie.util.XLog; |
| |
| public class StoreStatusFilter { |
| public static final String coordSeletStr = "Select w.id, w.appName, w.statusStr, w.user, w.group, w.startTimestamp, " + |
| "w.endTimestamp, w.appPath, w.concurrency, w.frequency, w.lastActionTimestamp, w.nextMaterializedTimestamp, " + |
| "w.createdTimestamp, w.timeUnitStr, w.timeZone, w.timeOut, w.bundleId from CoordinatorJobBean w"; |
| |
| public static final String coordCountStr = "Select count(w) from CoordinatorJobBean w"; |
| |
| public static final String wfSeletStr = "Select w.id, w.appName, w.statusStr, w.run, w.user, w.group, w.createdTimestamp, " + |
| "w.startTimestamp, w.lastModifiedTimestamp, w.endTimestamp from WorkflowJobBean w"; |
| |
| public static final String wfCountStr = "Select count(w) from WorkflowJobBean w"; |
| |
| public static final String bundleSeletStr = "Select w.id, w.appName, w.appPath, w.conf, w.statusStr, w.kickoffTimestamp, " + |
| "w.startTimestamp, w.endTimestamp, w.pauseTimestamp, w.createdTimestamp, w.user, w.group, w.timeUnitStr, " + |
| "w.timeOut from BundleJobBean w"; |
| |
| public static final String bundleCountStr = "Select count(w) from BundleJobBean w"; |
| |
| public static final String TIME_FORMAT = " Specify time either in UTC format (yyyy-MM-dd'T'HH:mm'Z') or " + |
| "a offset value in days/hours/minutes e.g. (-2d/h/m) from the current time."; |
| |
| private static final String textFilterStr = "(w.appName LIKE :text1 OR w.user LIKE :text2 OR w.id = :text3)"; |
| |
| |
| public static void filter(Map<String, List<String>> filter, List<String> orArray, List<String> colArray, |
| List<Object> valArray, StringBuilder sb, String seletStr, String countStr) throws JPAExecutorException { |
| boolean isStatus = false; |
| boolean isAppName = false; |
| boolean isUser = false; |
| boolean isEnabled = false; |
| boolean isFrequency = false; |
| boolean isId = false; |
| boolean isUnit = false; |
| |
| int index = 0; |
| |
| for (Map.Entry<String, List<String>> entry : filter.entrySet()) { |
| String colName = null; |
| String colVar = null; |
| if (entry.getKey().equals(OozieClient.FILTER_GROUP)) { |
| XLog.getLog(StoreStatusFilter.class).warn("Filter by 'group' is not supported anymore"); |
| } |
| else { |
| if (entry.getKey().equals(OozieClient.FILTER_STATUS)) { |
| List<String> values = filter.get(OozieClient.FILTER_STATUS); |
| colName = "status"; |
| for (int i = 0; i < values.size(); i++) { |
| colVar = "status"; |
| colVar = colVar + index; |
| if (!isEnabled && !isStatus) { |
| sb.append(seletStr).append(" where w.statusStr IN (:status" + index); |
| isStatus = true; |
| isEnabled = true; |
| } |
| else { |
| if (isEnabled && !isStatus) { |
| sb.append(" and w.statusStr IN (:status" + index); |
| isStatus = true; |
| } |
| else { |
| if (isStatus) { |
| sb.append(", :status" + index); |
| } |
| } |
| } |
| if (i == values.size() - 1) { |
| sb.append(")"); |
| } |
| index++; |
| valArray.add(values.get(i)); |
| orArray.add(colName); |
| colArray.add(colVar); |
| } |
| } |
| else { |
| if (entry.getKey().equals(OozieClient.FILTER_NAME)) { |
| List<String> values = filter.get(OozieClient.FILTER_NAME); |
| colName = "appName"; |
| for (int i = 0; i < values.size(); i++) { |
| colVar = "appName"; |
| colVar = colVar + index; |
| if (!isEnabled && !isAppName) { |
| sb.append(seletStr).append(" where w.appName IN (:appName" + index); |
| isAppName = true; |
| isEnabled = true; |
| } |
| else { |
| if (isEnabled && !isAppName) { |
| sb.append(" and w.appName IN (:appName" + index); |
| isAppName = true; |
| } |
| else { |
| if (isAppName) { |
| sb.append(", :appName" + index); |
| } |
| } |
| } |
| if (i == values.size() - 1) { |
| sb.append(")"); |
| } |
| index++; |
| valArray.add(values.get(i)); |
| orArray.add(colName); |
| colArray.add(colVar); |
| } |
| } |
| else { |
| if (entry.getKey().equals(OozieClient.FILTER_USER)) { |
| List<String> values = filter.get(OozieClient.FILTER_USER); |
| colName = "user"; |
| for (int i = 0; i < values.size(); i++) { |
| colVar = "user"; |
| colVar = colVar + index; |
| if (!isEnabled && !isUser) { |
| sb.append(seletStr).append(" where w.user IN (:user" + index); |
| isUser = true; |
| isEnabled = true; |
| } |
| else { |
| if (isEnabled && !isUser) { |
| sb.append(" and w.user IN (:user" + index); |
| isUser = true; |
| } |
| else { |
| if (isUser) { |
| sb.append(", :user" + index); |
| } |
| } |
| } |
| if (i == values.size() - 1) { |
| sb.append(")"); |
| } |
| index++; |
| valArray.add(values.get(i)); |
| orArray.add(colName); |
| colArray.add(colVar); |
| } |
| } |
| else if (entry.getKey().equals(OozieClient.FILTER_FREQUENCY)) { |
| List<String> values = filter.get(OozieClient.FILTER_FREQUENCY); |
| colName = "frequency"; |
| for (int i = 0; i < values.size(); i++) { |
| colVar = "frequency"; |
| colVar = colVar + index; |
| if (!isEnabled && !isFrequency) { |
| sb.append(seletStr).append(" where w.frequency IN (:frequency" + index); |
| isFrequency = true; |
| isEnabled = true; |
| } |
| else { |
| if (isEnabled && !isFrequency) { |
| sb.append(" and w.frequency IN (:frequency" + index); |
| isFrequency = true; |
| } |
| else { |
| if (isFrequency) { |
| sb.append(", :frequency" + index); |
| } |
| } |
| } |
| if (i == values.size() - 1) { |
| sb.append(")"); |
| } |
| index++; |
| valArray.add(values.get(i)); |
| orArray.add(colName); |
| colArray.add(colVar); |
| } |
| } |
| else if (entry.getKey().equals(OozieClient.FILTER_ID)) { |
| List<String> values = filter.get(OozieClient.FILTER_ID); |
| colName = "id"; |
| for (int i = 0; i < values.size(); i++) { |
| colVar = "id"; |
| colVar = colVar + index; |
| if (!isEnabled && !isId) { |
| sb.append(seletStr).append(" where w.id IN (:id" + index); |
| isId = true; |
| isEnabled = true; |
| } |
| else { |
| if (isEnabled && !isId) { |
| sb.append(" and w.id IN (:id" + index); |
| isId = true; |
| } |
| else { |
| if (isId) { |
| sb.append(", :id" + index); |
| } |
| } |
| } |
| if (i == values.size() - 1) { |
| sb.append(")"); |
| } |
| index++; |
| valArray.add(values.get(i)); |
| orArray.add(colName); |
| colArray.add(colVar); |
| } |
| } |
| // Filter map has time unit filter specified |
| else if (entry.getKey().equals(OozieClient.FILTER_UNIT)) { |
| List<String> values = filter.get(OozieClient.FILTER_UNIT); |
| colName = "timeUnitStr"; |
| for (int i = 0; i < values.size(); ++i) { |
| colVar = colName + index; |
| // This unit filter value is the first condition to be added to the where clause of |
| // query |
| if (!isEnabled && !isUnit) { |
| sb.append(seletStr).append(" where w.timeUnitStr IN (:timeUnitStr" + index); |
| isUnit = true; |
| isEnabled = true; |
| } else { |
| // Unit filter is neither the first nor the last condition to be added to the where |
| // clause of query |
| if (isEnabled && !isUnit) { |
| sb.append(" and w.timeUnitStr IN (:timeUnitStr" + index); |
| isUnit = true; |
| } else { |
| if (isUnit) { |
| sb.append(", :timeUnitStr" + index); |
| } |
| } |
| } |
| // This unit filter value is the last condition to be added to the where clause of query |
| if (i == values.size() - 1) { |
| sb.append(")"); |
| } |
| ++index; |
| valArray.add(values.get(i)); |
| orArray.add(colName); |
| colArray.add(colVar); |
| } |
| } |
| else if (entry.getKey().equalsIgnoreCase(OozieClient.FILTER_CREATED_TIME_START)) { |
| List<String> values = filter.get(OozieClient.FILTER_CREATED_TIME_START); |
| colName = "createdTimestampStart"; |
| if (values.size() > 1) { |
| throw new JPAExecutorException(ErrorCode.E0302, |
| "cannot specify multiple startcreatedtime"); |
| } |
| colVar = colName; |
| colVar = colVar + index; |
| if (!isEnabled) { |
| sb.append(seletStr).append(" where w.createdTimestamp >= :" + colVar); |
| isEnabled = true; |
| } |
| else { |
| sb.append(" and w.createdTimestamp >= :" + colVar); |
| } |
| index++; |
| Date createdTime = null; |
| try { |
| createdTime = parseCreatedTimeString(values.get(0)); |
| } |
| catch (Exception e) { |
| throw new JPAExecutorException(ErrorCode.E0302, e.getMessage()); |
| } |
| Timestamp createdTimeStamp = new Timestamp(createdTime.getTime()); |
| valArray.add(createdTimeStamp); |
| orArray.add(colName); |
| colArray.add(colVar); |
| |
| } |
| else if (entry.getKey().equalsIgnoreCase(OozieClient.FILTER_CREATED_TIME_END)) { |
| List<String> values = filter.get(OozieClient.FILTER_CREATED_TIME_END); |
| colName = "createdTimestampEnd"; |
| if (values.size() > 1) { |
| throw new JPAExecutorException(ErrorCode.E0302, |
| "cannot specify multiple endcreatedtime"); |
| } |
| colVar = colName; |
| colVar = colVar + index; |
| if (!isEnabled) { |
| sb.append(seletStr).append(" where w.createdTimestamp <= :" + colVar); |
| isEnabled = true; |
| } |
| else { |
| sb.append(" and w.createdTimestamp <= :" + colVar); |
| } |
| index++; |
| Date createdTime = null; |
| try { |
| createdTime = parseCreatedTimeString(values.get(0)); |
| } |
| catch (Exception e) { |
| throw new JPAExecutorException(ErrorCode.E0302, e.getMessage()); |
| } |
| Timestamp createdTimeStamp = new Timestamp(createdTime.getTime()); |
| valArray.add(createdTimeStamp); |
| orArray.add(colName); |
| colArray.add(colVar); |
| } |
| // job.id = text || job.appName.contains(text) || job.user.contains(text) |
| else if (entry.getKey().equalsIgnoreCase(OozieClient.FILTER_TEXT)) { |
| filterJobsUsingText(filter, sb, isEnabled, seletStr, valArray, orArray, colArray); |
| isEnabled = true; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private static Date parseCreatedTimeString(String time) throws Exception{ |
| Date createdTime = null; |
| int offset = 0; |
| if (Character.isLetter(time.charAt(time.length() - 1))) { |
| switch (time.charAt(time.length() - 1)) { |
| case 'd': |
| offset = Integer.parseInt(time.substring(0, time.length() - 1)); |
| if(offset > 0) { |
| throw new IllegalArgumentException("offset must be minus from currentTime."); |
| } |
| createdTime = org.apache.commons.lang3.time.DateUtils.addDays(new Date(), offset); |
| break; |
| case 'h': |
| offset = Integer.parseInt(time.substring(0, time.length() - 1)); |
| if(offset > 0) { |
| throw new IllegalArgumentException("offset must be minus from currentTime."); |
| } |
| createdTime = org.apache.commons.lang3.time.DateUtils.addHours(new Date(), offset); |
| break; |
| case 'm': |
| offset = Integer.parseInt(time.substring(0, time.length() - 1)); |
| if(offset > 0) { |
| throw new IllegalArgumentException("offset must be minus from currentTime."); |
| } |
| createdTime = org.apache.commons.lang3.time.DateUtils.addMinutes(new Date(), offset); |
| break; |
| case 'Z': |
| createdTime = DateUtils.parseDateUTC(time); |
| break; |
| default: |
| throw new IllegalArgumentException("Unsupported time format: " + time + TIME_FORMAT); |
| } |
| } else { |
| throw new IllegalArgumentException("The format of time is wrong: " + time + TIME_FORMAT); |
| } |
| return createdTime; |
| } |
| |
| public static String getSortBy(Map<String, List<String>> filter, String sortByStr) throws JPAExecutorException { |
| if (filter.containsKey(OozieClient.FILTER_SORT_BY)) { |
| List<String> values = filter.get(OozieClient.FILTER_SORT_BY); |
| if (values.size() > 1) { |
| throw new JPAExecutorException(ErrorCode.E0302, |
| "cannot specify multiple sortby parameter"); |
| } |
| String value = values.get(0); |
| for (OozieClient.SORT_BY sortBy : OozieClient.SORT_BY.values()) { |
| if (sortBy.toString().equalsIgnoreCase(value)) { |
| value = sortBy.getFullname(); |
| sortByStr = " order by w.".concat(value).concat(" desc "); |
| break; |
| } |
| } |
| } |
| return sortByStr; |
| } |
| |
| public static void filterJobsUsingText(Map<String, List<String>> filter, StringBuilder sb, boolean isEnabled, |
| String seletStr, List<Object> valArray, List<String> orArray, List<String> colArray) throws JPAExecutorException { |
| List<String> values = filter.get(OozieClient.FILTER_TEXT); |
| if (values.size() != 1) { |
| throw new JPAExecutorException(ErrorCode.E0302, |
| "cannot specify multiple strings to search"); |
| } |
| if (!isEnabled) { |
| sb.append(seletStr).append(" where " + textFilterStr); |
| } |
| else { |
| sb.append(" and " + textFilterStr); |
| } |
| |
| valArray.add("%" + values.get(0) + "%"); |
| orArray.add("appName"); |
| colArray.add("text1"); |
| |
| valArray.add("%" + values.get(0) + "%"); |
| orArray.add("user"); |
| colArray.add("text2"); |
| |
| valArray.add(values.get(0)); |
| orArray.add("id"); |
| colArray.add("text3"); |
| } |
| } |