001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.core.search;
034:
035: import com.flexive.shared.exceptions.FxSqlSearchException;
036: import com.flexive.shared.search.SortDirection;
037: import com.flexive.sqlParser.Property;
038: import com.flexive.sqlParser.Value;
039:
040: import java.util.ArrayList;
041: import java.util.List;
042:
043: import org.apache.commons.logging.Log;
044: import org.apache.commons.logging.LogFactory;
045:
046: /**
047: * Helper to store subselect values
048: *
049: * @author Gregor Schober (gregor.schober@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
050: * @version $Rev: 256 $
051: */
052: public class SubSelectValues {
053: private static final Log LOG = LogFactory
054: .getLog(SubSelectValues.class);
055:
056: private final int resultSetPos;
057: private final SortDirection sortDirection;
058: private final List<Item> items = new ArrayList<Item>();
059: private int values = 0;
060: private Value value = null;
061:
062: /**
063: * Constructor.
064: *
065: * @param resultSetPos the position within the resultset
066: * @param sortDirection the sort direction for this column
067: */
068: public SubSelectValues(int resultSetPos, SortDirection sortDirection) {
069: this .resultSetPos = resultSetPos;
070: this .sortDirection = sortDirection;
071: }
072:
073: public boolean isSorted() {
074: return !SortDirection.UNSORTED.equals(sortDirection);
075: }
076:
077: public boolean isSortedAscending() {
078: return SortDirection.ASCENDING.equals(sortDirection);
079: }
080:
081: public void addItem(String select, int resultSetPos, boolean isXpath) {
082: if (!isXpath)
083: values++;
084: items
085: .add(new Item(select, isXpath, resultSetPos, items
086: .size()));
087: }
088:
089: public List<Item> getItems() {
090: return items;
091: }
092:
093: public int getResultSetPos() {
094: return resultSetPos;
095: }
096:
097: /**
098: * Returns true if this object contains more than one select that is not the XPath.
099: *
100: * @return true if this object contains more than one select that is not the XPath
101: */
102: protected boolean isMultivalue() {
103: return values > 1;
104: }
105:
106: /**
107: * Applies any functions and reference selectors.
108: *
109: * @param ds the caller
110: * @param prop the property
111: * @param entry the entry
112: * @return the modified object itself
113: * @throws FxSqlSearchException if the function fails
114: */
115: public SubSelectValues prepare(DataSelector ds, Value prop,
116: PropertyEntry entry) throws FxSqlSearchException {
117: applySelector(ds, (Property) prop, entry);
118: applyWrapper(prop);
119: this .value = prop;
120: return this ;
121: }
122:
123: public Value getValue() {
124: return value;
125: }
126:
127: /**
128: * Applies the reference selector if needed.
129: *
130: * @param ds the caller
131: * @param prop the property
132: * @param entry the entry
133: * @throws FxSqlSearchException if the function fails
134: */
135: protected void applySelector(DataSelector ds, Property prop,
136: PropertyEntry entry) throws FxSqlSearchException {
137: // any selector to apply at all?
138: if (!prop.hasField()) {
139: return;
140: }
141:
142: // Find and apply the selector
143: if (isMultivalue()
144: || entry.getTableType() != PropertyResolver.Table.T_CONTENT) {
145: throw new FxSqlSearchException(LOG,
146: "ex.sqlSearch.query.fieldNotAllowedFor", prop
147: .getPropertyName());
148: }
149: final FieldSelector selector = ds.getSelectors().get(
150: prop.getPropertyName());
151: if (selector == null) {
152: throw new FxSqlSearchException(LOG,
153: "ex.sqlSearch.query.noFieldsForProp", prop
154: .getField(), prop.getPropertyName());
155: } else {
156: for (Item it : items) {
157: if (it.isXpath())
158: continue;
159: final StringBuffer tmp = new StringBuffer(it.select);
160: selector.apply(prop, entry, tmp);
161: it.setSelect(tmp.toString());
162: }
163: }
164: }
165:
166: /**
167: * Applies a prefix and suffix (eg a function) to the subselect item(s).
168: *
169: * @param prop the property
170: * @throws FxSqlSearchException if no prefix/suffix can be applied
171: */
172: protected void applyWrapper(Value prop) throws FxSqlSearchException {
173:
174: // anything to apply?
175: if (prop.getFunctionsStart().length() == 0
176: && prop.getFunctionsEnd().length() == 0)
177: return;
178:
179: if (isMultivalue()) {
180: throw new FxSqlSearchException(LOG,
181: "ex.sqlSearch.query.fieldNotAllowedFor",
182: (prop instanceof Property) ? ((Property) prop)
183: .getPropertyName() : "[constant]");
184: }
185: for (Item it : items) {
186: if (it.isXpath())
187: continue;
188: it.setSelect(prop.getFunctionsStart() + it.select
189: + prop.getFunctionsEnd());
190: }
191: }
192:
193: public static class Item {
194: private final String alias;
195: private final boolean isXpath;
196: private final boolean orderBy;
197: private String select;
198:
199: private Item(String select, boolean isXpath, int resultSetPos,
200: int pos) {
201: this .isXpath = isXpath;
202: this .select = select;
203: this .orderBy = !isXpath;
204: this .alias = "prop" + (isXpath ? "X" : "") + "_"
205: + resultSetPos + "_" + pos;
206: }
207:
208: public String getSelect() {
209: return select;
210: }
211:
212: public String getAlias() {
213: return alias;
214: }
215:
216: public boolean isOrderBy() {
217: return orderBy;
218: }
219:
220: public boolean isXpath() {
221: return isXpath;
222: }
223:
224: public void setSelect(String select) {
225: this.select = select;
226: }
227: }
228:
229: }
|