blob: bfde7bb5f700b6c148404d929c4347f345b0df64 [file] [log] [blame]
/*
* 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.ode.bpel.common;
import org.apache.ode.bpel.pmapi.InvalidRequestException;
import org.apache.ode.utils.ISO8601DateParser;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* Holds a filter that will get interpreted when listing processes. The semantic
* of the filtering is somewhat different than the one used in the ProcessQuery
* class. Here we're introducing a pseudo process querying language.
*/
public class ProcessFilter extends Filter<ProcessFilter.FilterKeysOp> implements
Serializable {
private static final long serialVersionUID = 9999;
/** If set, will filter on the process name (accepts ending with wildcard) */
private String nameFilter;
/** If set, will filter on the process name (accepts ending with wildcard) */
private String namespaceFilter;
/** If set, will filter on the process status (activated or retired) */
private String statusFilter;
/**
* If set, will filter on the process deployment date. Prefixed with a
* comparison operator (<, >, <=, >=, =). We're keeping a string and note
* converting to a java date as ISO string dates are much easier and quicker
* to manipulate. It's possible to have more than one date filter to handle
* the 'between' case.
*/
private List<String> deployedDateFilter;
/**
* List of additional information to include when producing the filter result,
* currently only 'properties' and 'instance' are supported.
*/
private List<String> includes;
/**
* Orders to use when sorting the result (no particular order if not set).
* Currently /supported keys are:
* <ul>
* <li>name</li>
* <li>namespace</li>
* <li>version</li>
* <li>status</li>
* <li>deployed</li>
* </ul>
* Each key can be prefixed with a + or - sign for ascending or descending
* orders (ascending if no sign specified)..
*/
private List<String> orders;
// Used both to validate filter keys and to process them
enum FilterKeysOp {
NAME {
void process(ProcessFilter filter, String op, String value) {
filter.nameFilter = value;
}
},
NAMESPACE {
void process(ProcessFilter filter, String op, String value) {
filter.namespaceFilter = value;
}
},
STATUS {
void process(ProcessFilter filter, String op, String value) {
filter.statusFilter = value;
}
},
DEPLOYED {
void process(ProcessFilter filter, String op, String value) {
if (filter.deployedDateFilter == null)
filter.deployedDateFilter = new ArrayList<String>();
filter.deployedDateFilter.add(op + value);
}
};
abstract void process(ProcessFilter filter, String op, String value);
}
enum OrderKeys {
NAME, NAMESPACE, VERSION, STATUS, DEPLOYED;
}
enum StatusKeys {
ACTIVATED, RETIRED;
}
/**
* Initializes properly the ProcessFilter attributes by pre-parsing the filter
* and orderKeys strings.
*
* @param filter
* @param orderKeys
*/
public ProcessFilter(String filter, String orderKeys) {
init(filter);
// Some additional validation on status value
if (statusFilter != null) {
try {
StatusKeys.valueOf(statusFilter.toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidRequestException(
"The status you're using in your filter isn't valid, "
+ "only the activated and retired status are valid. "
+ e.toString());
}
}
// Some additional validation on date format value
if (deployedDateFilter != null) {
for (String ddf : deployedDateFilter) {
try {
ISO8601DateParser.parse(getDateWithoutOp(ddf));
} catch (ParseException e) {
throw new InvalidRequestException(
"Couldn't parse one of the filter date, please make "
+ "sure it follows the ISO-8601 date or date/time standard (yyyyMMddhhmmss). "
+ e.toString());
}
}
}
if (orderKeys != null && orderKeys.length() > 0) {
orders = new ArrayList<String>(3);
for (StringTokenizer orderKeysTok = new StringTokenizer(orderKeys, " "); orderKeysTok
.hasMoreTokens();) {
String orderKey = orderKeysTok.nextToken();
try {
String justKey = orderKey;
if (justKey.startsWith("-") || justKey.startsWith("+"))
justKey = orderKey.substring(1, justKey.length());
OrderKeys.valueOf(justKey.toUpperCase());
orders.add(orderKey);
} catch (IllegalArgumentException e) {
throw new InvalidRequestException(
"One of the ordering keys isn't valid, processes can only "
+ "be sorted by name, namespace, version, status and deployed date."
+ e.toString());
}
}
}
}
public String getNameFilter() {
return nameFilter;
}
public String getNamespaceFilter() {
return namespaceFilter;
}
public String getStatusFilter() {
return statusFilter;
}
public List<String> getDeployedDateFilter() {
return deployedDateFilter;
}
public List<String> getIncludes() {
return includes;
}
public List<String> getOrders() {
return orders;
}
public static void main(String[] args) {
ProcessFilter pf = new ProcessFilter("name = dtc* status=activated "
+ "deployed>=2005-11-29T15:12 deployed < 2005-11-29T15:13",
"status name -version");
System.out.println("=> " + pf);
}
@Override
protected FilterKeysOp parseKey(String keyVal) {
return FilterKeysOp.valueOf(keyVal);
}
@Override
protected FilterKeysOp[] getFilterKeys() {
return FilterKeysOp.values();
}
@Override
protected void process(FilterKeysOp key, Restriction<String> rest) {
key.process(this, rest.op, rest.value);
}
}