/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.persistence; import com.servoy.base.query.IBaseSQLCondition; import com.servoy.base.scripting.annotations.ServoyClientSupport; import com.servoy.j2db.documentation.ServoyDocumented; import com.servoy.j2db.query.ISQLCondition; import com.servoy.j2db.util.UUID; /** * @author jblok */ @ServoyDocumented(category = ServoyDocumented.DESIGNTIME, typeCode = IRepository.RELATION_ITEMS) @ServoyClientSupport(mc = true, wc = true, sc = true) public class RelationItem extends AbstractBase implements ISupportContentEquals, IPersistCloneable, ICloneable { private static final long serialVersionUID = 1L; public static final int[] RELATION_OPERATORS = new int[] { // standard set ISQLCondition.EQUALS_OPERATOR, ISQLCondition.GT_OPERATOR, ISQLCondition.LT_OPERATOR, ISQLCondition.GTE_OPERATOR, ISQLCondition.LTE_OPERATOR, ISQLCondition.NOT_OPERATOR, ISQLCondition.IN_OPERATOR, ISQLCondition.LIKE_OPERATOR, ISQLCondition.NOT_LIKE_OPERATOR, // case insensitive ISQLCondition.EQUALS_OPERATOR | ISQLCondition.CASEINSENTITIVE_MODIFIER, ISQLCondition.NOT_OPERATOR | ISQLCondition.CASEINSENTITIVE_MODIFIER, ISQLCondition.LIKE_OPERATOR | ISQLCondition.CASEINSENTITIVE_MODIFIER, ISQLCondition.NOT_LIKE_OPERATOR | ISQLCondition.CASEINSENTITIVE_MODIFIER, // or null ISQLCondition.EQUALS_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.GT_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.LT_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.GTE_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.LTE_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.NOT_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.IN_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.LIKE_OPERATOR | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.NOT_LIKE_OPERATOR | ISQLCondition.ORNULL_MODIFIER, // case insensitive or null ISQLCondition.EQUALS_OPERATOR | ISQLCondition.CASEINSENTITIVE_MODIFIER | ISQLCondition.ORNULL_MODIFIER, ISQLCondition.NOT_OPERATOR | ISQLCondition.CASEINSENTITIVE_MODIFIER | ISQLCondition.ORNULL_MODIFIER, // }; /** * Constructor I */ RelationItem(ISupportChilds parent, int element_id, UUID uuid) { super(IRepository.RELATION_ITEMS, parent, element_id, uuid); } /* * _____________________________________________________________ Methods from this class */ /** * Set the tableName1 * * @param arg the tableName1 */ public void setPrimaryDataProviderID(String arg) { setTypedProperty(StaticContentSpecLoader.PROPERTY_PRIMARYDATAPROVIDERID, arg); } /** * The name of the column from the source table * that this relation item is based on. */ public String getPrimaryDataProviderID() { return getTypedProperty(StaticContentSpecLoader.PROPERTY_PRIMARYDATAPROVIDERID); } /** * Set the foreignTableName * * @param arg the foreignTableName */ public void setForeignColumnName(String arg) { setTypedProperty(StaticContentSpecLoader.PROPERTY_FOREIGNCOLUMNNAME, arg); } /** * The name of the column from the destination table * that this relation item is based on. */ public String getForeignColumnName() { return getTypedProperty(StaticContentSpecLoader.PROPERTY_FOREIGNCOLUMNNAME); } public static String getOperatorAsString(int op) { if ((op & IBaseSQLCondition.OPERATOR_MASK) == op) { // no modifiers return IBaseSQLCondition.OPERATOR_STRINGS[op]; } StringBuffer sb = new StringBuffer(); for (int i = 0; i < IBaseSQLCondition.ALL_MODIFIERS.length; i++) { if ((op & IBaseSQLCondition.ALL_MODIFIERS[i]) != 0) { sb.append(IBaseSQLCondition.MODIFIER_STRINGS[i]); } } sb.append(IBaseSQLCondition.OPERATOR_STRINGS[op & IBaseSQLCondition.OPERATOR_MASK]); return sb.toString(); } /** * Swap the operator, leave the modifier in place * * @param op */ public static int swapOperator(int op) { int swapped; switch (op & IBaseSQLCondition.OPERATOR_MASK) { case IBaseSQLCondition.GT_OPERATOR : swapped = IBaseSQLCondition.LT_OPERATOR; break; case IBaseSQLCondition.LT_OPERATOR : swapped = IBaseSQLCondition.GT_OPERATOR; break; case IBaseSQLCondition.GTE_OPERATOR : swapped = IBaseSQLCondition.LTE_OPERATOR; break; case IBaseSQLCondition.LTE_OPERATOR : swapped = IBaseSQLCondition.GTE_OPERATOR; break; case IBaseSQLCondition.NOT_OPERATOR : swapped = IBaseSQLCondition.NOT_OPERATOR; break; case IBaseSQLCondition.EQUALS_OPERATOR : swapped = IBaseSQLCondition.EQUALS_OPERATOR; break; //we have made like an exception since global like column doesn't make any sense. case IBaseSQLCondition.LIKE_OPERATOR : swapped = IBaseSQLCondition.LIKE_OPERATOR; break; case IBaseSQLCondition.NOT_LIKE_OPERATOR : swapped = IBaseSQLCondition.NOT_LIKE_OPERATOR; break; default : return -1; } return swapped | (op & ~IBaseSQLCondition.OPERATOR_MASK); } public static boolean checkIfValidOperator(String op) { return getValidOperator(op, RELATION_OPERATORS, null) != -1; } private static int parseOperatorString(String operatorString) { if (operatorString == null) { return -1; } String opString = operatorString; int mod = 0; boolean foundModifiers = true; while (foundModifiers) { foundModifiers = false; for (int m = 0; m < IBaseSQLCondition.ALL_MODIFIERS.length; m++) { if (opString.startsWith(IBaseSQLCondition.MODIFIER_STRINGS[m])) { foundModifiers = true; opString = opString.substring(IBaseSQLCondition.MODIFIER_STRINGS[m].length()); mod |= IBaseSQLCondition.ALL_MODIFIERS[m]; break; } } } for (int i = 0; i < IBaseSQLCondition.OPERATOR_STRINGS.length; i++) { if (IBaseSQLCondition.OPERATOR_STRINGS[i].equalsIgnoreCase(opString)) { return IBaseSQLCondition.ALL_DEFINED_OPERATORS[i] | mod; } } // not found return -1; } /** * Parse the operator string '[<modifier>]<operator>' * * @param str * @param operators includes modifiers when modifiers is null * @param modifiers */ public static int getValidOperator(String str, int[] operators, int[] modifiers) { int operator = parseOperatorString(str); if (operator == -1) { return -1; } // check against valid operators and modifiers if (modifiers == null) { // operators contains values including modifiers for (int element : operators) { if (element == operator) { return operator; } } return -1; } // operators and modifiers are separate int mod = operator & ~IBaseSQLCondition.OPERATOR_MASK; for (int x : IBaseSQLCondition.ALL_MODIFIERS) { mod &= ~x; } if (mod != 0) { // illegal modifiers left return -1; } int op = operator & IBaseSQLCondition.OPERATOR_MASK; for (int x : operators) { if (x == op) { return operator; } } // not allowed return -1; } /** * The operator that defines the relationship between the primary dataprovider * and the foreign column. */ public int getOperator() { return getTypedProperty(StaticContentSpecLoader.PROPERTY_OPERATOR).intValue(); } /** * Sets the operator. * * @param operator The operator to set */ public void setOperator(int operator) { setTypedProperty(StaticContentSpecLoader.PROPERTY_OPERATOR, operator); } public boolean contentEquals(Object obj) { if (obj instanceof RelationItem) { RelationItem other = (RelationItem)obj; return (getPrimaryDataProviderID().equals(other.getPrimaryDataProviderID()) && getOperator() == other.getOperator() && getForeignColumnName() == other.getForeignColumnName()); } return false; } }