package adql.query; /* * This file is part of ADQLLibrary. * * ADQLLibrary is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ADQLLibrary 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012 - UDS/Centre de DonnĂ©es astronomiques de Strasbourg (CDS) */ import java.util.Vector; import adql.query.constraint.ADQLConstraint; /** * <p>Represents a clause which deals with {@link ADQLConstraint}s (i.e. WHERE, HAVING).</p> * * <p>The logical operators AND (see {@link ClauseConstraints#AND}) and OR (see {@link ClauseConstraints#OR}) are managed * in a separated list by this class. To add a constraint you can use the default add functions or use the one defined by this class: * <ul> * <li> {@link ClauseConstraints#add(String, ADQLConstraint) add(String, ADQLConstraint}: which lets you specify the logical operator * between the added constraint (index=size()) and the previous one (index=size()-1) in the list.</li> * <li> {@link ClauseConstraints#add(int, String, ADQLConstraint) add(int, String, ADQLConstraint}: which lets you specify * the logical operator between the added constraint (index) and the previous one (index-1) in the list.</li> * </ul></p> * * <p>If no logical separator is specified the default one is used (see {@link ClauseConstraints#getDefaultSeparator() getDefaultSeparator()}). * The only way to set this default separator is during the {@link ClauseConstraints} creation * (see {@link ClauseConstraints#ClauseConstraints(String, String) ClauseConstraints(String, String)}).</p> * * @author Grégory Mantelet (CDS) * @version 01/2012 * * @see adql.query.constraint.ConstraintsGroup */ public class ClauseConstraints extends ClauseADQL<ADQLConstraint> { /** The logical separator OR <i>(By default, the default separator (see {@link ClauseConstraints#getDefaultSeparator() getDefaultSeparator()}) is equals to OR)</i>. */ public final static String OR = "OR"; /** The logical separator AND. */ public final static String AND = "AND"; /** The logical separator used when none is specified during a constraint insertion <i>(by default = {@link ClauseConstraints#OR OR})</i>. */ protected final String defaultSeparator; /** The used separators for the constraints list (vSeparators.size() = size()-1 ; * vSeparators.get(i) gives the separator between get(i-1) and get(i)). */ private Vector<String> vSeparators = new Vector<String>(); /** * <p>Builds a constraints list with only its name (which will prefix the whole list).</p> * * <p><i><u>Note:</u> The default separator is automatically set to OR.</i></p> * * @param name The name/prefix of the list. */ public ClauseConstraints(String name){ super(name); defaultSeparator = OR; } /** * <p>Builds a constraints list with its name and its default separator.</p> * * <p><i><u>Note:</u> if the given separator is no {@link ClauseConstraints#AND} * or {@link ClauseConstraints#OR}, the default separator is automatically set to {@link ClauseConstraints#OR}.</i></p> * * @param name The name/prefix of the list. * @param logicalSep The constraints separator (a logical separator: {@link ClauseConstraints#AND} or {@link ClauseConstraints#OR}). * * @see ClauseConstraints#checkSeparator(String) */ public ClauseConstraints(String name, String logicalSep){ super(name); defaultSeparator = checkSeparator(logicalSep); } /** * <p>Builds a ClauseConstraints by copying the given one.</p> * * @param toCopy The ClauseConstraints to copy. * @throws Exception If there is an error during the copy. * * @see ClauseConstraints#checkSeparator(String) */ public ClauseConstraints(ClauseConstraints toCopy) throws Exception{ super(toCopy); defaultSeparator = checkSeparator(toCopy.defaultSeparator); } /** * Gets the default constraints separator ({@link ClauseConstraints#AND} or {@link ClauseConstraints#OR}). * * @return The default separator. */ public final String getDefaultSeparator(){ return defaultSeparator; } /** * Checks/Converts the given separator in one of the two logical separators. * If the given separator is neither AND nor OR, then the returned separator is {@link ClauseConstraints#OR OR}. * * @param sepToCheck The separator to check/convert. * @return The understood separator (OR if neither AND nor OR). */ public final static String checkSeparator(String sepToCheck){ if (sepToCheck != null && sepToCheck.equalsIgnoreCase(AND)) return AND; else return OR; } /** * @see adql.query.ADQLList#add(adql.query.ADQLObject) * @see ClauseConstraints#add(String, ADQLConstraint) */ @Override public boolean add(ADQLConstraint constraint) throws NullPointerException{ return add(defaultSeparator, constraint); } /** * @see adql.query.ADQLList#add(int, adql.query.ADQLObject) * @see ClauseConstraints#add(int, String, ADQLConstraint) */ @Override public void add(int index, ADQLConstraint constraint) throws NullPointerException, ArrayIndexOutOfBoundsException{ add(index, defaultSeparator, constraint); } /** * Adds the given constraint with the given separator. The separator is added just before the added constraint, * that is to say between the last constraint of the list and the added one. * * @param logicalSep The separator to add just before the given constraint. * @param constraint The constraint to add. * @return <i>true</i> if the constraint has been successfully added, <i>false</i> otherwise. * @throws NullPointerException If the given constraint is <i>null</i>. * * @see ADQLList#add(ADQLObject) * @see ClauseConstraints#checkSeparator(String) */ public boolean add(String logicalSep, ADQLConstraint constraint) throws NullPointerException{ boolean added = super.add(constraint); if (added && size() > 1) vSeparators.add(checkSeparator(logicalSep)); return added; } /** * Adds the given constraint with the given separator at the given position in the constraints list. * The separator is added just before the added constraint, that is to say between the (index-1)-th constraint of the list and the added one (at the index position). * * @param index Position at which the given constraint must be added. * @param logicalSep The constraints separator to add just before the given constraint. * @param constraint The constraint to add. * @throws NullPointerException If the given constraint is <i>null</i>. * @throws ArrayIndexOutOfBoundsException If the given index is incorrect (index < 0 || index >= size()). * * @see ADQLList#add(int, ADQLObject) * @see ClauseConstraints#checkSeparator(String) */ public void add(int index, String logicalSep, ADQLConstraint constraint) throws NullPointerException, ArrayIndexOutOfBoundsException{ super.add(index, constraint); if (index > 0) vSeparators.add(index - 1, checkSeparator(logicalSep)); } /** * @see adql.query.ADQLList#set(int, adql.query.ADQLObject) * @see ClauseConstraints#set(int, String, ADQLConstraint) */ @Override public ADQLConstraint set(int index, ADQLConstraint constraint) throws NullPointerException, ArrayIndexOutOfBoundsException{ return set(index, null, constraint); } /** * Replaces the specified constraint by the given one with the given constraint separator. * The separator is added just before the added constraint, that is to say between the (index-1)-th constraint of the list and the added one (at the index position). * * @param index Position of the constraint to replace. * @param logicalSep The separator to insert just before the given constraint (if <i>null</i>, the previous separator is kept). * @param constraint The replacer. * @return The replaced constraint. * @throws NullPointerException If the given constraint is <i>null</i>. * @throws ArrayIndexOutOfBoundsException If the given index is incorrect (index < 0 || index >= size()). * * @see ADQLList#set(int, ADQLObject) */ public ADQLConstraint set(int index, String logicalSep, ADQLConstraint constraint) throws NullPointerException, ArrayIndexOutOfBoundsException{ ADQLConstraint replaced = super.set(index, constraint); if (replaced != null && logicalSep != null && index > 0) vSeparators.set(index - 1, logicalSep); return replaced; } @Override public void clear(){ super.clear(); vSeparators.clear(); } @Override public ADQLConstraint remove(int index) throws ArrayIndexOutOfBoundsException{ ADQLConstraint removed = super.remove(index); if (removed != null) if (index > 0) vSeparators.remove(index - 1); else if (index == 0) vSeparators.remove(index); return removed; } @Override public ADQLObject getCopy() throws Exception{ return new ClauseConstraints(this); } /** * Only two values in this case: the both logical separators: {@link ClauseConstraints#AND AND} and {@link ClauseConstraints#OR OR}. * * @see adql.query.ADQLList#getPossibleSeparators() */ @Override public String[] getPossibleSeparators(){ return new String[]{AND,OR}; } @Override public String getSeparator(int index) throws ArrayIndexOutOfBoundsException{ if (index <= 0 || index > size()) throw new ArrayIndexOutOfBoundsException("Impossible to get the logical separator between the item " + (index - 1) + " and " + index + " !"); else return vSeparators.get(index - 1); } }