001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance 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 */ 018package org.fcrepo.search.api; 019 020import java.util.regex.Pattern; 021 022/** 023 * A data structure representing a search condition. 024 * 025 * @author dbernstein 026 */ 027public class Condition { 028 public enum Operator { 029 LTE("<="), 030 GTE(">="), 031 EQ("="), 032 GT(">"), 033 LT("<"); 034 035 private String value; 036 037 Operator(final String value) { 038 this.value = value; 039 } 040 041 public String getStringValue() { 042 return this.value; 043 } 044 045 public static Operator fromString(final String str) { 046 for (final Operator o : Operator.values()) { 047 if (o.value.equals(str)) { 048 return o; 049 } 050 } 051 052 throw new IllegalArgumentException("Value " + str + " not recognized."); 053 } 054 055 } 056 057 public enum Field { 058 FEDORA_ID, 059 MODIFIED, 060 CREATED, 061 CONTENT_SIZE, 062 MIME_TYPE, 063 RDF_TYPE; 064 065 @Override 066 public String toString() { 067 return super.toString().toLowerCase(); 068 } 069 070 public static Field fromString(final String fieldStr) { 071 return Field.valueOf(fieldStr.toUpperCase()); 072 } 073 } 074 075 /* A regex for parsing the value of a "condition" query parameter which follows the format 076 * [field_name][operation][object] 077 * The field name is composed of at least one character and can contain alpha number characters and underscores. 078 * The operation can equal "=", "<", ">", "<=" or ">=" 079 * The object can be anything but cannot start with >, <, and =. 080 */ 081 final static Pattern CONDITION_REGEX = Pattern.compile("([a-zA-Z0-9_]+)([><=]|<=|>=)([^><=].*)"); 082 083 084 private Field field; 085 private Operator operator; 086 private String object; 087 088 /** 089 * Internal constructor 090 * 091 * @param field The search field (condition subject) 092 * @param operator The operator (condition predicate) 093 * @param object The object (condition object) 094 */ 095 private Condition(final Field field, final Operator operator, final String object) { 096 this.field = field; 097 this.operator = operator; 098 this.object = object; 099 } 100 101 /** 102 * Field accessor 103 * 104 * @return the field 105 */ 106 public Field getField() { 107 return field; 108 } 109 110 /** 111 * Operator accessor 112 * @return the operator 113 */ 114 public Operator getOperator() { 115 return operator; 116 } 117 118 /** 119 * @return the object portion of the condition 120 */ 121 public String getObject() { 122 return object; 123 } 124 125 @Override 126 public String toString() { 127 return this.field.toString().toLowerCase() + operator + object; 128 } 129 130 /** 131 * Parses a string expression into a Condition object. 132 * @param expression The condition as a string expression. 133 * @return The condition 134 * @throws InvalidConditionExpressionException if we can't parse the string into a Condition. 135 */ 136 public static Condition fromExpression(final String expression) throws InvalidConditionExpressionException { 137 final var m = CONDITION_REGEX.matcher(expression); 138 if (m.matches()) { 139 final var field = Field.fromString(m.group(1)); 140 final var operation = Operator.fromString(m.group(2)); 141 final var object = m.group(3); 142 return fromEnums(field, operation, object); 143 } 144 145 throw new InvalidConditionExpressionException(expression); 146 } 147 148 public static Condition fromEnums(final Field field, final Operator operator, final String expression) { 149 return new Condition(field, operator, expression); 150 } 151}