0001: /*
0002: * The contents of this file are subject to the
0003: * Mozilla Public License Version 1.1 (the "License");
0004: * you may not use this file except in compliance with the License.
0005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
0006: *
0007: * Software distributed under the License is distributed on an "AS IS"
0008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
0009: * See the License for the specific language governing rights and
0010: * limitations under the License.
0011: *
0012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
0013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
0014: *
0015: * All Rights Reserved.
0016: *
0017: * Contributor(s):
0018: */
0019: package org.openharmonise.rm.search;
0020:
0021: import java.sql.*;
0022: import java.util.*;
0023: import java.util.logging.*;
0024:
0025: import org.openharmonise.commons.cache.CacheException;
0026: import org.openharmonise.commons.dsi.*;
0027: import org.openharmonise.commons.dsi.dml.*;
0028: import org.openharmonise.commons.xml.*;
0029: import org.openharmonise.rm.*;
0030: import org.openharmonise.rm.config.*;
0031: import org.openharmonise.rm.dsi.DataStoreObject;
0032: import org.openharmonise.rm.factory.*;
0033: import org.openharmonise.rm.metadata.*;
0034: import org.openharmonise.rm.publishing.*;
0035: import org.openharmonise.rm.resources.*;
0036: import org.openharmonise.rm.resources.lifecycle.Status;
0037: import org.openharmonise.rm.resources.metadata.properties.*;
0038: import org.openharmonise.rm.resources.metadata.properties.ranges.Range;
0039: import org.openharmonise.rm.resources.publishing.*;
0040: import org.openharmonise.rm.security.authorization.*;
0041: import org.w3c.dom.*;
0042:
0043: /**
0044: * <p>Provides an interface to construct and run searches over
0045: * resources within the repository, allowing metadata conditions to be
0046: * specified using implementations of <code>AbstractPropertyInstance</code>
0047: * core data conditions to be specified using <code>ColumnRef</code>.
0048: * The class also implements <code>Publishable</code> in order that
0049: * a search can be specified in HaRP and the results can be published
0050: * as XML.</p>
0051: *
0052: * @author Michael Bell
0053: * @version $Revision: 1.10 $
0054: *
0055: */
0056: public class Search implements Publishable {
0057:
0058: private boolean m_bCache = true;
0059:
0060: //XML constants
0061: public static final String ATTRIB_ORDERBY = "orderBy";
0062:
0063: public static final String ATTRIB_ORDER_DIRECTION = "orderDirection";
0064:
0065: public static final String ATTRIB_OBJECT_TYPE = "objectType";
0066:
0067: public static final String TAG_SEARCH = "Search";
0068:
0069: public static final String TAG_LIST = "List";
0070:
0071: public static final String ATTRIB_MAXRESULTS = "maxResults";
0072:
0073: public static final String TAG_SEARCHTEXT = "SearchText";
0074:
0075: public static final String TAG_FURTHERLINKS = "FurtherLinks";
0076:
0077: public static final String TAG_NUMBER = "Number";
0078:
0079: public static final String TAG_SEARCHCONDITIONS = "SearchConditions";
0080:
0081: public static final String TAG_SEARCH_OBJECT = "SearchObject";
0082:
0083: public static final String TAG_CONDITIONS = "Conditions";
0084:
0085: public static final String TAG_FILTERCONDITIONS = "FilterConditions";
0086:
0087: public static final String TAG_FILTERSOURCE = "FilterSource";
0088:
0089: public static final String TAG_SUBMIT = "Submit";
0090:
0091: public static final String ATTRIB_STRICT_TYPING = "strictTyping";
0092:
0093: public static final String TAG_COMMENT = "Comment";
0094:
0095: public static final String TAG_POSITION = "Position";
0096:
0097: public static final String TAG_DISPLAY = "Display";
0098:
0099: public static final String TAG_TOTAL = "Total";
0100:
0101: public static final String ATTRIB_SUB = "sub";
0102:
0103: public static final String ATTRIB_SELECTED = "selected";
0104:
0105: public static final String ATTRIB_INCLUSIVE = "inclusive";
0106:
0107: public static final String TAG_AND = "And";
0108:
0109: public static final String TAG_OR = "Or";
0110:
0111: private static String PNAME_RESULTSET_CACHING = "RESULTSET_CACHING";
0112:
0113: /**
0114: * Vector of WhereCondition objects, all of the columns that an object
0115: * manages itself.
0116: */
0117: protected List m_ConditionColumns = null;
0118:
0119: /**
0120: * Vector of GroupObjects identifying which groups should be in the search
0121: */
0122: protected List m_ConditionGroups = null;
0123:
0124: /**
0125: * the properties to be used in the search
0126: */
0127: protected List m_ConditionProfile = null;
0128:
0129: /**
0130: * Vector of ColumnRefs, identifies which columns should be returned
0131: */
0132: protected List m_SearchColumns = null;
0133:
0134: /**
0135: * Vector of Properties, identifies which Properties should be returned
0136: */
0137: protected List m_SearchProfile = null;
0138:
0139: /**
0140: * String operator to link the condition profile properties
0141: */
0142: protected String m_ConditionOperator = "and";
0143:
0144: protected Map m_orderByPropMap = new LinkedHashMap();
0145:
0146: protected Map m_orderByColMap = new LinkedHashMap();
0147:
0148: protected String m_sOrderDirection = "ASC";
0149:
0150: protected int m_nLimit = -1;
0151:
0152: //position in the results the listings should start from
0153: protected int m_nPosition = 0;
0154:
0155: protected String m_sSearchType = "";
0156:
0157: protected String m_sSearchText = "";
0158:
0159: protected DataStoreObject m_searchObject = null;
0160:
0161: protected Profile m_searchObjectProfile = null;
0162:
0163: protected boolean m_bApprovedSearch = true;
0164:
0165: protected String m_sFilterObjectClassname = null;
0166:
0167: protected Vector m_filterProps = null;
0168:
0169: protected AbstractDataStoreInterface m_dsi = null;
0170:
0171: protected String m_sId = "";
0172:
0173: protected String m_sName = "";
0174:
0175: protected int m_nResultTotal = -1;
0176:
0177: protected boolean m_bStrictType = true;
0178:
0179: // set in getIndexSearchQuery if correct columns exist
0180: protected boolean m_bIndexableSearch = false;
0181:
0182: protected CachedResultSet m_cached_rs = null;
0183:
0184: protected boolean m_bFilterCondsNotFound = false;
0185:
0186: protected boolean m_bFilterCondsInclusive = false;
0187:
0188: private List m_indexresults = null;
0189:
0190: private boolean m_bIsCachingRS = false;
0191:
0192: private String m_sCacheKey = null;
0193:
0194: /**
0195: * Logger for this class
0196: */
0197: private static final Logger m_logger = Logger
0198: .getLogger(Search.class.getName());
0199:
0200: //initialising block
0201: {
0202: m_ConditionColumns = new Vector(16);
0203: m_ConditionGroups = new Vector(16);
0204: m_ConditionProfile = new Vector(16);
0205:
0206: m_SearchColumns = new Vector(16);
0207: m_SearchProfile = new Vector(16);
0208: }
0209:
0210: /**
0211: * Basic constructor
0212: *
0213: */
0214: public Search() {
0215: }
0216:
0217: /**
0218: * Standard constructor with interface to the DB.
0219: *
0220: * @param dbinterf
0221: */
0222: public Search(AbstractDataStoreInterface dbinterf) {
0223: m_dsi = dbinterf;
0224: }
0225:
0226: /**
0227: * Returns an object of the type that the search will be conducted on.
0228: *
0229: * @return
0230: */
0231: public DataStoreObject getSearchType() {
0232: return m_searchObject;
0233: }
0234:
0235: /**
0236: * Sets the object type that the search will be conducted on.
0237: *
0238: * @param dobj
0239: * @throws DataStoreException
0240: */
0241: public void setSearchType(DataStoreObject dobj)
0242: throws DataStoreException {
0243:
0244: if (m_searchObject != null) {
0245: if (dobj instanceof AbstractProfiledObject) {
0246: AbstractProfiledObject profObj = (AbstractProfiledObject) dobj;
0247:
0248: try {
0249: m_searchObjectProfile = profObj.getProfile();
0250: } catch (DataAccessException e) {
0251: m_searchObjectProfile = null;
0252: }
0253:
0254: if (m_searchObjectProfile == null) {
0255: m_searchObjectProfile = new Profile(m_dsi, profObj);
0256: }
0257: Profile prof = m_searchObjectProfile;
0258:
0259: for (int i = 0; i < this .m_ConditionProfile.size(); i++) {
0260: AbstractPropertyInstance propInst = (AbstractPropertyInstance) m_ConditionProfile
0261: .get(i);
0262: propInst.setProfile(prof);
0263: }
0264:
0265: for (int i = 0; i < this .m_SearchProfile.size(); i++) {
0266: AbstractPropertyInstance propInst = (AbstractPropertyInstance) m_ConditionProfile
0267: .get(i);
0268: propInst.setProfile(prof);
0269: }
0270: }
0271:
0272: m_SearchColumns.clear();
0273: m_SearchColumns.add(dobj.getInstanceColumnRef(
0274: AbstractObject.ATTRIB_ID, ((AbstractObject) dobj)
0275: .isHistorical()));
0276: m_ConditionColumns.clear();
0277: m_orderByPropMap.clear();
0278: m_orderByColMap.clear();
0279: }
0280:
0281: m_searchObject = dobj;
0282: m_sSearchType = dobj.getClass().getName();
0283:
0284: ColumnRef colrefId = m_searchObject.getInstanceColumnRef(
0285: AbstractObject.ATTRIB_ID,
0286: ((AbstractObject) m_searchObject).isHistorical());
0287:
0288: if (colrefId != null) {
0289: addSelectColumn(colrefId);
0290: }
0291:
0292: if (m_sSearchType.indexOf(".") >= 0) {
0293: int index = m_sSearchType.lastIndexOf(".");
0294: m_sSearchType = m_sSearchType.substring(index + 1);
0295: }
0296: }
0297:
0298: /**
0299: * Sets the maximum size of the list of results.
0300: *
0301: * @param nNum
0302: */
0303: public void setResultSize(int nNum) {
0304: this .m_nLimit = nNum;
0305: }
0306:
0307: /**
0308: * Sets the column which will be used for ordering the results as well as
0309: * the direction of the ordering.
0310: *
0311: * @param colref
0312: * @param sOrderDirection
0313: */
0314: public void setOrderBy(ColumnRef colref, String sOrderDirection) {
0315: m_orderByColMap.put(colref, sOrderDirection);
0316: }
0317:
0318: /**
0319: * Sets the property instance which should be used to order the search
0320: * results as well as the direction of the ordering.
0321: *
0322: * @param propInst
0323: * @param sOrderDirection
0324: */
0325: public void setOrderBy(AbstractPropertyInstance propInst,
0326: String sOrderDirection) {
0327: m_orderByPropMap.put(propInst, sOrderDirection);
0328: }
0329:
0330: /**
0331: * Returns a <code>Set</code> of <code>ColumnRef</code>s which
0332: * represents the column by which the results will be ordered.
0333: *
0334: * @return a <code>Set</code> of <code>ColumnRef</code>s
0335: */
0336: public Set getOrderByColumns() {
0337: return m_orderByColMap.keySet();
0338: }
0339:
0340: /* (non-Javadoc)
0341: * @see org.openharmonise.rm.publishing.Publishable#getTagName()
0342: */
0343: public String getTagName() {
0344:
0345: return TAG_SEARCH;
0346: }
0347:
0348: /**
0349: * Returns the direction the results will be ordered in
0350: * for the specified column reference.
0351: *
0352: * @return the direction the results will be ordered in
0353: * for the specified column reference
0354: */
0355: public String getOrderDirection(ColumnRef colref) {
0356: return (String) m_orderByColMap.get(colref);
0357: }
0358:
0359: /**
0360: * Adds a condition to the search. Defined by column, operator and value.
0361: *
0362: * @param colref
0363: * @param sOperator
0364: * @param values
0365: * @throws DataStoreException
0366: */
0367: public void addConditionColumn(ColumnRef colref, String sOperator,
0368: Vector values) throws DataStoreException {
0369: WhereCondition where = new WhereCondition(colref, sOperator,
0370: values);
0371:
0372: m_ConditionColumns.add(where);
0373: }
0374:
0375: /**
0376: * Adds a relationship condition to the search such that results will be
0377: * children of the given <code>AbstractParentObject</code>.
0378: *
0379: * @param grpObj
0380: */
0381: public void addConditionGroup(AbstractParentObject grpObj) {
0382: if (grpObj != null) {
0383: m_ConditionGroups.add(grpObj);
0384: }
0385: }
0386:
0387: /**
0388: * Adds a condition to this search which is defined by the given
0389: * <code>AbstractPropertyInstance</code>.
0390: *
0391: * @param propInst
0392: */
0393: public void addConditionProperty(AbstractPropertyInstance propInst) {
0394: m_ConditionProfile.add(propInst);
0395: }
0396:
0397: /**
0398: * Adds conditions to the search defined by the given <code>Profile</code>,
0399: * i.e. the conditions will be specified by the property instances the
0400: * profile contains.
0401: *
0402: * @param prof
0403: * @throws DataAccessException
0404: */
0405: public void addConditionProfile(Profile prof)
0406: throws DataAccessException {
0407: m_ConditionProfile.addAll(prof.getPropertyInstances());
0408: }
0409:
0410: /**
0411: * Adds a select column to be returned in the search. Objects which are
0412: * returned will be populated with this data from the executed search as an
0413: * optimisation.
0414: *
0415: * Note: the column referenced will be associated to the object's core data
0416: * rather than profile data
0417: *
0418: * @param colref
0419: */
0420: public void addSelectColumn(ColumnRef colref) {
0421: m_SearchColumns.add(colref);
0422: }
0423:
0424: /**
0425: * Adds a select column to be returned in the search which corresponds to
0426: * the given property instance. Objects which are returned will be populated
0427: * with this data from the executed search as an optimisation.
0428: *
0429: * @param propInst
0430: */
0431: public void addSelectProperty(AbstractPropertyInstance propInst) {
0432: m_SearchProfile.add(propInst);
0433: }
0434:
0435: /**
0436: * Executed the search and returns a vector of objects representing the
0437: * results of the search.
0438: *
0439: * @return @throws
0440: * SearchException
0441: * @throws HarmoniseIndexerException
0442: * @throws DataAccessException
0443: * @throws DataStoreException
0444: */
0445: public List executeSearch() throws SearchException,
0446: HarmoniseIndexerException, DataAccessException,
0447: DataStoreException {
0448: Vector results = null;
0449:
0450: SelectStatement select = generateSelectStatement();
0451:
0452: //if no cached results do DB query
0453: if (m_cached_rs == null) {
0454: ResultSet rs = null;
0455:
0456: if ((m_bIndexableSearch == false)
0457: || (m_indexresults != null && m_indexresults.size() > 0)) {
0458:
0459: if (m_logger.isLoggable(Level.FINE)) {
0460: m_logger.logp(Level.FINE,
0461: this .getClass().getName(), "executeSearch",
0462: "Executing search - "
0463: + m_dsi.getSelectStatement(select));
0464: }
0465:
0466: rs = m_dsi.execute(select);
0467:
0468: m_cached_rs = new CachedResultSet(rs);
0469: }
0470:
0471: if (rs != null) {
0472: try {
0473: rs.close();
0474: } catch (SQLException e) {
0475: throw new SearchException(
0476: "Error closing result set", e);
0477: }
0478: }
0479:
0480: if ((m_cached_rs != null) && (m_bIsCachingRS == true)) {
0481: if (m_logger.isLoggable(Level.FINE)) {
0482: m_logger.log(Level.FINE,
0483: "Caching search results for "
0484: + m_dsi.getSelectStatement(select));
0485: }
0486: try {
0487: SearchResultsCache.getInstance().addToCache(
0488: m_sCacheKey, m_cached_rs);
0489: } catch (CacheException e) {
0490: throw new SearchException("Cache error", e);
0491: }
0492: } else {
0493: if (m_logger.isLoggable(Level.FINE)) {
0494: m_logger.log(Level.FINE,
0495: "Not caching search results");
0496: }
0497: }
0498: } else {
0499: if (m_logger.isLoggable(Level.FINE)) {
0500: m_logger.log(Level.FINE, "Got cached search results");
0501: }
0502: }
0503:
0504: //fill return vector with objects
0505: List returnVec = new Vector(16);
0506:
0507: if (m_cached_rs != null) {
0508: m_cached_rs.setStartRow(m_nPosition);
0509:
0510: //if no limit is set this should be default value of -1
0511: returnVec = m_searchObject.processResultSet(m_cached_rs,
0512: select, m_nLimit - m_nPosition);
0513:
0514: m_nResultTotal = m_cached_rs.getResultTotal();
0515: }
0516:
0517: return returnVec;
0518: }
0519:
0520: public SelectStatement generateSelectStatement()
0521: throws SearchException, HarmoniseIndexerException,
0522: DataAccessException, DataStoreException {
0523: //build query
0524: SelectStatement select = new SelectStatement();
0525:
0526: //add the select colomn refs to the select statement
0527: select.addSelectColumns(m_SearchColumns);
0528:
0529: if (m_orderByColMap.isEmpty() == false) {
0530: select.addOrderBy(m_orderByColMap);
0531: }
0532:
0533: HarmoniseIndexer indexer = HarmoniseIndexer.getInstance();
0534:
0535: //get index query if applicable
0536: String sIndexQuery = "";
0537:
0538: if (this .m_bApprovedSearch == true) {
0539: sIndexQuery = getIndexSearchQuery();
0540:
0541: if (m_logger.isLoggable(Level.FINE)) {
0542: m_logger.log(Level.FINE, "Index search:" + sIndexQuery);
0543: }
0544: }
0545:
0546: //add conditions to select statement
0547: addWhereConditions(select);
0548:
0549: m_sCacheKey = sIndexQuery + "|"
0550: + this .m_dsi.getSelectStatement(select);
0551:
0552: //try and get cached results
0553: m_bIsCachingRS = m_bCache;
0554:
0555: if (m_bCache == true) {
0556: try {
0557: m_bIsCachingRS = ConfigSettings.getProperty(
0558: PNAME_RESULTSET_CACHING, "ON").equals("ON");
0559:
0560: if (m_bIsCachingRS == true) {
0561: if (m_logger.isLoggable(Level.FINE)) {
0562: m_logger.logp(Level.FINER, this .getClass()
0563: .getName(), "generateSelectStatement",
0564: "Getting cached results for "
0565: + m_sCacheKey);
0566: }
0567: m_cached_rs = SearchResultsCache.getInstance()
0568: .getResults(m_sCacheKey);
0569: if (m_logger.isLoggable(Level.FINE)
0570: && m_cached_rs == null) {
0571: m_logger.logp(Level.FINER, this .getClass()
0572: .getName(), "generateSelectStatement",
0573: "No results cached");
0574: }
0575: }
0576: } catch (ConfigException e) {
0577: throw new SearchException("Config error", e);
0578: } catch (CacheException e) {
0579: throw new SearchException("Cache error", e);
0580: }
0581: }
0582:
0583: if (m_cached_rs == null) {
0584: m_indexresults = null;
0585: if ((sIndexQuery != null) && (sIndexQuery.length() > 0)) {
0586: m_indexresults = indexer.searchContents(sIndexQuery);
0587:
0588: if (m_logger.isLoggable(Level.FINE)) {
0589: m_logger
0590: .log(Level.FINE, "there was "
0591: + m_indexresults.size()
0592: + " lucene results");
0593: }
0594:
0595: select.addWhereCondition(this .m_searchObject
0596: .getInstanceColumnRef(AbstractObject.ATTRIB_ID,
0597: ((AbstractObject) m_searchObject)
0598: .isHistorical()), "IN",
0599: (Vector) m_indexresults);
0600:
0601: }
0602: }
0603:
0604: return select;
0605: }
0606:
0607: /* (non-Javadoc)
0608: * @see org.openharmonise.rm.publishing.Publishable#publish(org.openharmonise.rm.resources.publishing.Template, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
0609: */
0610: public org.w3c.dom.Element publish(Template template,
0611: HarmoniseOutput xmlDoc, State state)
0612: throws PublishException {
0613: Element resultEl = null;
0614:
0615: try {
0616:
0617: resultEl = publish(template.getTemplateRootElement(),
0618: xmlDoc, state);
0619: } catch (DataAccessException e) {
0620: throw new PublishException(e);
0621: }
0622:
0623: return resultEl;
0624: }
0625:
0626: /* (non-Javadoc)
0627: * @see org.openharmonise.rm.publishing.Publishable#publish(org.w3c.dom.Element, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
0628: */
0629: public org.w3c.dom.Element publish(Element topEl,
0630: HarmoniseOutput xmlDoc, State state)
0631: throws PublishException {
0632: Element docEl;
0633:
0634: String sTagname = topEl.getTagName();
0635:
0636: if (m_logger.isLoggable(Level.FINE)) {
0637: m_logger.log(Level.FINE, "Publishing " + sTagname
0638: + " element");
0639: }
0640:
0641: if (sTagname.equalsIgnoreCase(TAG_LIST)) {
0642: if (m_logger.isLoggable(Level.FINE)) {
0643: m_logger.log(Level.FINE, "Publishing as List element");
0644: }
0645: docEl = list(topEl, xmlDoc, state);
0646: } else if (sTagname.equalsIgnoreCase(TAG_SEARCH)) {
0647: if (m_logger.isLoggable(Level.FINE)) {
0648: m_logger
0649: .log(Level.FINE, "Publishing as Search element");
0650: }
0651: docEl = search(topEl, xmlDoc, state);
0652: } else {
0653: if (m_logger.isLoggable(Level.FINE)) {
0654: m_logger.log(Level.FINE, "Didn't recognise element");
0655: }
0656: docEl = (Element) xmlDoc.copyNode(topEl);
0657: }
0658:
0659: return docEl;
0660: }
0661:
0662: /* (non-Javadoc)
0663: * @see org.openharmonise.rm.publishing.Publishable#populate(org.w3c.dom.Element, org.openharmonise.rm.publishing.State)
0664: */
0665: public void populate(Element xmlElement, State state)
0666: throws PopulateException {
0667: if ((xmlElement.getTagName().equals(TAG_SEARCH) == false)
0668: && (xmlElement.getTagName().equals(TAG_LIST) == false)) {
0669: throw new PopulateException("Expected either " + TAG_SEARCH
0670: + " or " + TAG_LIST + " got "
0671: + xmlElement.getTagName());
0672: }
0673:
0674: boolean bIsList = false;
0675:
0676: if (xmlElement.getTagName().equals(TAG_LIST)) {
0677: bIsList = true;
0678: }
0679:
0680: if (xmlElement.getAttribute(AbstractObject.ATTRIB_ID)
0681: .equals("") == false) {
0682: m_sId = xmlElement.getAttribute(AbstractObject.ATTRIB_ID);
0683: }
0684:
0685: if (xmlElement.getAttribute(AbstractObject.ATTRIB_NAME).equals(
0686: "") == false) {
0687: m_sName = xmlElement
0688: .getAttribute(AbstractObject.ATTRIB_NAME);
0689: }
0690:
0691: if (xmlElement.getAttribute(ATTRIB_MAXRESULTS).equals("") == false) {
0692: m_nLimit = Integer.parseInt(xmlElement
0693: .getAttribute(ATTRIB_MAXRESULTS));
0694: }
0695:
0696: // get the child nodes for the type of search
0697: // either list of search
0698: NodeList nodes = xmlElement.getChildNodes();
0699: Element formEl;
0700: Text txt;
0701: String sTagName;
0702: Profile pro;
0703:
0704: // go through each one of them
0705: for (int i = 0; i < nodes.getLength(); i++) {
0706: if (nodes.item(i).getNodeType() == Node.TEXT_NODE) {
0707: continue;
0708: }
0709: formEl = (Element) nodes.item(i);
0710: sTagName = formEl.getTagName();
0711:
0712: if (sTagName.equalsIgnoreCase(TAG_SEARCHTEXT)) {
0713: setSearchText(XMLDocument.getChildTextNodeValue(formEl));
0714: } else if (sTagName.equalsIgnoreCase(TAG_CONDITIONS)) {
0715: if (bIsList) {
0716: try {
0717: processSearchConditions(formEl, state);
0718: } catch (PublishException e) {
0719: throw new PopulateException(
0720: "Error occurred processing search conditions: ",
0721: e);
0722: }
0723: }
0724: } else if (sTagName.equalsIgnoreCase(TAG_SUBMIT)) {
0725: } else if (sTagName.equalsIgnoreCase(TAG_SEARCH_OBJECT) == true) {
0726: String sSearchTypeTag = "";
0727: Element elm = null;
0728:
0729: NodeList searchObjectNodes = formEl.getChildNodes();
0730: // get all the child nodes
0731:
0732: for (int j = 0; j < searchObjectNodes.getLength()
0733: && sSearchTypeTag.equals(""); j++) {
0734: if (searchObjectNodes.item(j).getNodeType() != Node.ELEMENT_NODE) {
0735: continue;
0736: }
0737:
0738: elm = (Element) searchObjectNodes.item(j); // get the
0739: // element
0740: sSearchTypeTag = elm.getTagName(); // get the tag name
0741: }
0742:
0743: if (sSearchTypeTag.equals("") == true) {
0744: throw new PopulateException(
0745: "Template Tag or Tag for Search object (e.g <Document/>) must be provided");
0746: } else if (sSearchTypeTag.equals(Template.TAG_TEMPLATE) == true) {
0747: try {
0748:
0749: Template tmplt = (Template) HarmoniseObjectFactory
0750: .instantiateHarmoniseObject(
0751: m_dsi,
0752: Template.class.getName(),
0753: Integer
0754: .parseInt(elm
0755: .getAttribute(AbstractObject.ATTRIB_ID)));
0756:
0757: setSearchType(tmplt.getTemplateRootElement());
0758: } catch (NumberFormatException e) {
0759: throw new PopulateException(
0760: "Number format exception", e);
0761: } catch (DataAccessException e) {
0762: throw new PopulateException(
0763: "Error occured getting template root element",
0764: e);
0765: } catch (SearchException e) {
0766: throw new PopulateException("Search error", e);
0767: } catch (DataStoreException e) {
0768: throw new PopulateException("Data store error",
0769: e);
0770: } catch (HarmoniseFactoryException e) {
0771: throw new PopulateException(e);
0772: }
0773: } else {
0774: try {
0775: setSearchType(elm);
0776: } catch (SearchException e) {
0777: throw new PopulateException(
0778: "Problem ocurred while attempting to set search type",
0779: e);
0780: } catch (PopulateException e) {
0781: throw new PopulateException(
0782: "Problem ocurred while attempting to set search type",
0783: e);
0784: } catch (DataStoreException e) {
0785: throw new PopulateException(
0786: "Problem ocurred while attempting to set search type",
0787: e);
0788: }
0789: }
0790: }
0791: }
0792: }
0793:
0794: /**
0795: * Adds the sub groups of the given <code>AbstractParentObject</code> as
0796: * conditions of this search.
0797: *
0798: * @param grpObj
0799: * @throws DataAccessException
0800: */
0801: public void addSubGroupsAsConditions(AbstractParentObject grpObj)
0802: throws DataAccessException {
0803: if (grpObj != null) {
0804: List subGrps = grpObj
0805: .getChildrenByType(AbstractParentObject.BRANCH_NODES);
0806:
0807: for (int i = 0; i < subGrps.size(); i++) {
0808: AbstractParentObject sub = (AbstractParentObject) subGrps
0809: .get(i);
0810: this .addConditionGroup(sub);
0811: addSubGroupsAsConditions(sub);
0812: }
0813: }
0814:
0815: }
0816:
0817: /*-------------------------------------------------------------------
0818: Protected methods
0819: ------------------------------------------------------------------*/
0820:
0821: /**
0822: * Publishes the 'List' element. Executes the search defined by the XML and
0823: * returns XML which will be a list of results published as specified by the
0824: * 'Template' child element of 'List'.
0825: *
0826: * @param list
0827: * @param output
0828: * @param state
0829: * @return @throws
0830: * PublishException
0831: */
0832: protected Element list(Element list, HarmoniseOutput output,
0833: State state) throws PublishException {
0834: if (m_logger.isLoggable(Level.FINE)) {
0835: m_logger.log(Level.FINE, "Executing list method");
0836: }
0837:
0838: boolean bMore = false;
0839: NodeList nodes;
0840: int nMorePage = -2;
0841: int nPageId = state.getPageId();
0842: Profile usrProf = state.getLoggedInUserProfile();
0843:
0844: Element newList = output.createElement(TAG_LIST);
0845:
0846: if ((m_sName == null) || (m_sName.length() == 0)) {
0847: m_sName = list.getAttribute(AbstractObject.ATTRIB_NAME);
0848: }
0849:
0850: newList.setAttribute(AbstractObject.ATTRIB_NAME, m_sName);
0851:
0852: if ((m_sId == null) || (m_sId.length() == 0)) {
0853: m_sId = list.getAttribute(AbstractObject.ATTRIB_ID);
0854: }
0855:
0856: String sStringTyping = list.getAttribute(ATTRIB_STRICT_TYPING);
0857:
0858: if ((sStringTyping != null) && (sStringTyping.length() > 0)
0859: && (sStringTyping.equalsIgnoreCase("false") == true)) {
0860: this .m_bStrictType = false;
0861: }
0862:
0863: newList.setAttribute(AbstractObject.ATTRIB_ID, m_sId);
0864:
0865: if (list.getElementsByTagName("*").getLength() == 0) {
0866: return newList;
0867: }
0868:
0869: Element searchObjectElm = (Element) XMLUtils
0870: .getFirstNamedChild(list, TAG_SEARCH_OBJECT);
0871:
0872: if (searchObjectElm == null) {
0873: throw new PublishException("SearchObject Tag is missing.");
0874: }
0875:
0876: String sTagName = "";
0877: Element elm = null;
0878:
0879: nodes = searchObjectElm.getChildNodes(); // get all the child nodes
0880:
0881: for (int i = 0; i < nodes.getLength() && sTagName.equals(""); i++) {
0882: if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
0883: continue;
0884: }
0885:
0886: elm = (Element) nodes.item(i); // get the element
0887: sTagName = elm.getTagName(); // get the tag name
0888: }
0889:
0890: Template template = null;
0891: int nTemplatePageId = -2;
0892:
0893: if (sTagName.equals("") == true) {
0894: throw new PublishException(
0895: "Template Tag or Tag for Search object (e.g <Document/>) must be provided");
0896: } else if (sTagName.equals(Template.TAG_TEMPLATE) == true) {
0897: NodeList pageNodes = elm
0898: .getElementsByTagName(WebPage.TAG_PAGE);
0899:
0900: if (pageNodes.getLength() > 0) {
0901: nTemplatePageId = Integer.parseInt(((Element) pageNodes
0902: .item(0))
0903: .getAttribute(AbstractObject.ATTRIB_ID));
0904: }
0905:
0906: try {
0907: template = (Template) HarmoniseObjectFactory
0908: .instantiateHarmoniseObject(
0909: m_dsi,
0910: Template.class.getName(),
0911: Integer
0912: .parseInt(elm
0913: .getAttribute(AbstractObject.ATTRIB_ID)));
0914: } catch (NumberFormatException e) {
0915: throw new PublishException(e);
0916: } catch (HarmoniseFactoryException e) {
0917: throw new PublishException(e);
0918: }
0919:
0920: if (template != null) {
0921: try {
0922: Element root = template.getTemplateRootElement();
0923:
0924: setSearchType(root);
0925: } catch (DataAccessException e) {
0926: throw new PublishException(
0927: "Error getting template root", e);
0928: } catch (SearchException e) {
0929: throw new PublishException("search error", e);
0930: } catch (PopulateException e) {
0931: throw new PublishException("Populate error", e);
0932: } catch (DataStoreException e) {
0933: throw new PublishException("Data store error", e);
0934: }
0935: } else {
0936: throw new InvalidXMLElementException(
0937: "Template element not found");
0938: }
0939: } else {
0940: try {
0941: setSearchType(elm);
0942: } catch (SearchException e) {
0943: throw new PublishException(
0944: "Problem ocurred while attempting to set search type",
0945: e);
0946: } catch (PopulateException e) {
0947: throw new PublishException(
0948: "Problem ocurred while attempting to set search type",
0949: e);
0950: } catch (DataStoreException e) {
0951: throw new PublishException(
0952: "Problem ocurred while attempting to set search type",
0953: e);
0954: }
0955: }
0956:
0957: //sort out searchconditions if necessary
0958: nodes = list.getElementsByTagName(TAG_CONDITIONS);
0959:
0960: Element searchCondEl = null;
0961: Element stateCondEl = null;
0962:
0963: if (nodes.getLength() > 0) {
0964: searchCondEl = (Element) nodes.item(0);
0965: stateCondEl = state.findElement(searchCondEl);
0966:
0967: //conditions from state override conditions in input xml
0968: if (stateCondEl != null) {
0969: searchCondEl = stateCondEl;
0970: }
0971:
0972: //if the conditions has 'conditions'
0973: if (searchCondEl.hasChildNodes()) {
0974: processSearchConditions(searchCondEl, state);
0975: }
0976: }
0977:
0978: nodes = list.getElementsByTagName(TAG_FILTERCONDITIONS);
0979:
0980: for (int i = 0; i < nodes.getLength(); i++) {
0981: Element elFilterConds = (Element) nodes.item(i);
0982:
0983: if (elFilterConds.getParentNode().getNodeName()
0984: .equalsIgnoreCase(TAG_LIST)) {
0985: Profile fListCondProf = createFilterConditionsProfile(
0986: elFilterConds, state);
0987:
0988: try {
0989: if (fListCondProf.match(usrProf) == false) {
0990: Element elComment = output
0991: .createElement(TAG_COMMENT);
0992: Text txt = output
0993: .createTextNode("User failed list match");
0994: elComment.appendChild(txt);
0995:
0996: return elComment;
0997: }
0998: } catch (ProfileException e) {
0999: throw new PublishException(
1000: "Error occured matching profiles", e);
1001: }
1002: } else if (elFilterConds.getParentNode().getNodeName()
1003: .equalsIgnoreCase(Template.TAG_TEMPLATE)) {
1004: //get filter condition for template and add to search
1005: // conditions
1006: addFilterSourceConditions(elFilterConds, state);
1007: }
1008: }
1009:
1010: int nNumber = -1;
1011: int nMaxResults = -1;
1012: String sTemp = list.getAttribute(ATTRIB_MAXRESULTS);
1013:
1014: if ((sTemp != null) && (sTemp.length() > 0)) {
1015: nMaxResults = Integer.parseInt(sTemp);
1016: nNumber = nMaxResults;
1017:
1018: m_nLimit = m_nPosition + nNumber;
1019: }
1020:
1021: List results = new Vector();
1022:
1023: if ((m_bFilterCondsInclusive == false)
1024: || (m_bFilterCondsNotFound == false)) {
1025: try {
1026: results = executeSearch();
1027: } catch (SearchException e) {
1028: throw new PublishException(
1029: "Error occured executing search", e);
1030: } catch (HarmoniseIndexerException e) {
1031: throw new PublishException(
1032: "Error occured with indexer", e);
1033: } catch (DataAccessException e) {
1034: throw new PublishException("data access error", e);
1035: } catch (DataStoreException e) {
1036: throw new PublishException("data store error", e);
1037: }
1038: }
1039:
1040: if (nNumber == -1) {
1041: nNumber = results.size();
1042: }
1043:
1044: nodes = list.getElementsByTagName(TAG_FURTHERLINKS);
1045:
1046: Element xnFurtherLinks = null;
1047:
1048: if (nodes.getLength() > 0) {
1049: bMore = true;
1050:
1051: NodeList xnlPages = ((Element) nodes.item(0))
1052: .getElementsByTagName(WebPage.TAG_PAGE);
1053:
1054: if (xnlPages.getLength() > 0) {
1055: nMorePage = Integer.parseInt(((Element) xnlPages
1056: .item(0))
1057: .getAttribute(AbstractObject.ATTRIB_ID));
1058: }
1059: }
1060:
1061: publishResults(newList, output, state, template, results,
1062: nTemplatePageId);
1063:
1064: if (nMorePage == -1) {
1065: nMorePage = nPageId;
1066: }
1067:
1068: //add more link if appropriate
1069: if ((m_nResultTotal > m_nPosition + nNumber) && bMore) {
1070: if (xnFurtherLinks == null) {
1071: xnFurtherLinks = output.createElement(TAG_FURTHERLINKS);
1072: }
1073:
1074: xnFurtherLinks.appendChild(createFurtherLinkElement(output,
1075: "More", m_nPosition + nNumber, nMorePage));
1076: }
1077:
1078: //Add prev link if appropriate
1079: if ((nNumber != 0) && ((m_nPosition + 1) > nNumber)) {
1080: if (xnFurtherLinks == null) {
1081: xnFurtherLinks = output.createElement(TAG_FURTHERLINKS);
1082: }
1083:
1084: xnFurtherLinks.appendChild(createFurtherLinkElement(output,
1085: "Previous", m_nPosition - nNumber, nMorePage));
1086: }
1087:
1088: if (xnFurtherLinks != null) {
1089: newList.appendChild(xnFurtherLinks);
1090: }
1091:
1092: Element xnState = output.createElement(State.TAG_STATE);
1093:
1094: Element xnCond = output.createElement(TAG_CONDITIONS);
1095:
1096: //set Condition name attribute to same as List
1097: xnCond.setAttribute(AbstractObject.ATTRIB_NAME, m_sName);
1098: xnState.appendChild(xnCond);
1099:
1100: //if there are search conditions in the state append these
1101: if (searchCondEl != null) {
1102: NodeList nlSearchCond = searchCondEl.getChildNodes();
1103:
1104: for (int i = 0; i < nlSearchCond.getLength(); i++) {
1105: Node node = nlSearchCond.item(i);
1106:
1107: if (node.getNodeType() != Node.ELEMENT_NODE) {
1108: continue;
1109: }
1110:
1111: xnCond.appendChild(output.importNode(node, true));
1112: }
1113: }
1114:
1115: if ((searchCondEl == null)
1116: || (searchCondEl.getElementsByTagName(TAG_POSITION)
1117: .getLength() == 0)) {
1118: Element xnPosition = output.createElement(TAG_POSITION);
1119: Text txtPos = output.createTextNode(Integer
1120: .toString(m_nPosition));
1121: xnPosition.appendChild(txtPos);
1122: xnCond.appendChild(xnPosition);
1123: }
1124:
1125: Element xnTotal = output.createElement(TAG_TOTAL);
1126: Text txtTotal = output.createTextNode(Integer
1127: .toString(m_nResultTotal));
1128: xnTotal.appendChild(txtTotal);
1129: xnCond.appendChild(xnTotal);
1130:
1131: if (nMaxResults > 0) {
1132: Element xnDisplay = output.createElement(TAG_DISPLAY);
1133: Text txtNumber = output.createTextNode(Integer
1134: .toString(nMaxResults));
1135: xnDisplay.appendChild(txtNumber);
1136: xnCond.appendChild(xnDisplay);
1137: }
1138:
1139: newList.appendChild(xnState);
1140:
1141: NodeList submitEls = list.getElementsByTagName(TAG_SUBMIT);
1142:
1143: for (int i = 0; i < submitEls.getLength(); i++) {
1144: newList.appendChild(output.copyNode(submitEls.item(i)));
1145: }
1146:
1147: return newList;
1148: }
1149:
1150: /**
1151: * Publishes the results contained in <code>results</code> using the given
1152: * <code>Template</code> under the <code>Element</code> <code>list</code>.
1153: *
1154: * @param list
1155: * @param output
1156: * @param state
1157: * @param template
1158: * @param results
1159: * @param nPageId
1160: * @throws PublishException
1161: */
1162: protected void publishResults(Element list, HarmoniseOutput output,
1163: State state, Template template, List results, int nPageId)
1164: throws PublishException {
1165: boolean bIsViewable = true;
1166:
1167: try {
1168: WebPage page = (WebPage) HarmoniseObjectFactory
1169: .instantiateHarmoniseObject(this .m_dsi,
1170: WebPage.class.getName(), nPageId);
1171:
1172: if (AuthorizationValidator.isVisible(state
1173: .getLoggedInUser(), page) == false) {
1174: bIsViewable = false;
1175: }
1176: } catch (HarmoniseFactoryException e) {
1177: throw new PublishException(
1178: "Error occured getting object from factory", e);
1179: } catch (AuthorizationException e) {
1180: throw new PublishException(
1181: "Error checking permissions on object", e);
1182: }
1183:
1184: for (Iterator iter = results.iterator(); iter.hasNext();) {
1185: Publishable pObj = (Publishable) iter.next();
1186:
1187: Element tmpEl = pObj.publish(template, output, state);
1188:
1189: NodeList linkNodes = tmpEl
1190: .getElementsByTagName(AbstractObject.TAG_LINK);
1191:
1192: if (linkNodes.getLength() > 0) {
1193: Element linkNode = (Element) linkNodes.item(0);
1194:
1195: if (bIsViewable == false) {
1196: linkNode.setAttribute(
1197: AuthorizationValidator.ATTRIB_IS_VIEWABLE,
1198: "false");
1199: }
1200:
1201: NodeList pageNodes = linkNode
1202: .getElementsByTagName(WebPage.TAG_PAGE);
1203:
1204: if (pageNodes.getLength() == 0) {
1205: Node pageNode = output
1206: .createElement(WebPage.TAG_PAGE);
1207: ((Element) pageNode).setAttribute(
1208: AbstractObject.ATTRIB_ID, Integer
1209: .toString(nPageId));
1210:
1211: linkNode.appendChild(pageNode);
1212: }
1213: }
1214:
1215: list.appendChild(tmpEl);
1216:
1217: }
1218: }
1219:
1220: /**
1221: * Publishes the 'Search' element, at most fills in available values for
1222: * property instances.
1223: *
1224: * @param search
1225: * @param output
1226: * @param state
1227: * @return @throws
1228: * PublishException
1229: */
1230: protected Element search(Element search, HarmoniseOutput output,
1231: State state) throws PublishException {
1232: Element newSearch = output.createElement(TAG_SEARCH);
1233: String sSearchName = search
1234: .getAttribute(AbstractObject.ATTRIB_NAME);
1235: newSearch.setAttribute(AbstractObject.ATTRIB_NAME, sSearchName);
1236: newSearch.setAttribute(AbstractObject.ATTRIB_ID, search
1237: .getAttribute(AbstractObject.ATTRIB_ID));
1238:
1239: NodeList children = search.getChildNodes();
1240:
1241: for (int i = 0; i < children.getLength(); i++) {
1242: if (children.item(i).getNodeType() != Node.ELEMENT_NODE) {
1243: continue;
1244: }
1245:
1246: Element elTemp = (Element) children.item(i);
1247: String sTagName = elTemp.getTagName();
1248:
1249: if (sTagName.equalsIgnoreCase(TAG_SEARCHTEXT)) {
1250: Element searchtext = output
1251: .createElement(TAG_SEARCHTEXT);
1252: m_sSearchText = ((Text) elTemp.getFirstChild())
1253: .getNodeValue();
1254:
1255: Text txt = output.createTextNode(this .m_sSearchText);
1256: searchtext.appendChild(txt);
1257: newSearch.appendChild(searchtext);
1258: } else if (sTagName.equalsIgnoreCase(TAG_CONDITIONS)) {
1259: Element condEl = output.createElement(TAG_CONDITIONS);
1260: String sCondName = elTemp
1261: .getAttribute(AbstractObject.ATTRIB_NAME);
1262: condEl.setAttribute(AbstractObject.ATTRIB_NAME,
1263: sCondName);
1264:
1265: NodeList nodes = elTemp.getChildNodes();
1266:
1267: for (int j = 0; j < nodes.getLength(); j++) {
1268: if (nodes.item(j).getNodeType() != Node.ELEMENT_NODE) {
1269: continue;
1270: }
1271:
1272: Element subEl = (Element) nodes.item(j);
1273:
1274: if (subEl.getTagName().equalsIgnoreCase(
1275: AbstractChildObject.TAG_GROUP)) {
1276: Element groupEl = output
1277: .createElement(AbstractChildObject.TAG_GROUP);
1278: groupEl.setAttribute(ATTRIB_SUB, subEl
1279: .getAttribute(ATTRIB_SUB));
1280:
1281: NodeList groupNodes = subEl
1282: .getElementsByTagName(Template.TAG_TEMPLATE);
1283:
1284: if (groupNodes.getLength() > 0) {
1285: Element templateEl = (Element) groupNodes
1286: .item(0);
1287: Template tmplt = null;
1288: try {
1289: tmplt = (Template) HarmoniseObjectFactory
1290: .instantiateHarmoniseObject(
1291: m_dsi,
1292: Template.class
1293: .getName(),
1294: Integer
1295: .parseInt(templateEl
1296: .getAttribute(AbstractObject.ATTRIB_ID)));
1297: } catch (NumberFormatException e) {
1298: throw new PublishException(e);
1299: } catch (HarmoniseFactoryException e) {
1300: throw new PublishException(e);
1301: }
1302: Element child = (Element) templateEl
1303: .getElementsByTagName("*").item(0);
1304: try {
1305: AbstractParentObject grpObj = (AbstractParentObject) HarmoniseObjectFactory
1306: .instantiatePublishableObject(
1307: this .m_dsi, child,
1308: state);
1309: groupEl.appendChild(grpObj.publish(
1310: tmplt, output, state));
1311:
1312: if (subEl.getAttribute(ATTRIB_SUB)
1313: .equalsIgnoreCase("true")) {
1314: List subGrps = grpObj
1315: .getChildrenByType(AbstractParentObject.BRANCH_NODES);
1316:
1317: for (int k = 0; k < subGrps.size(); k++) {
1318: AbstractParentObject sub = (AbstractParentObject) subGrps
1319: .get(k);
1320: groupEl.appendChild(sub
1321: .publish(tmplt, output,
1322: state));
1323: }
1324: }
1325: } catch (HarmoniseFactoryException e) {
1326: throw new PublishException(
1327: "Factory exception", e);
1328: } catch (DataAccessException e) {
1329: throw new PublishException(
1330: "Data access exception", e);
1331: }
1332: }
1333:
1334: condEl.appendChild(groupEl);
1335: } else if (subEl.getTagName().equalsIgnoreCase(
1336: Template.TAG_TEMPLATE)) {
1337: Element el = (Element) subEl
1338: .getElementsByTagName("*").item(0);
1339:
1340: try {
1341: Publishable pobj = HarmoniseObjectFactory
1342: .instantiatePublishableObject(
1343: this .m_dsi, el, state);
1344:
1345: Template tmplt = (Template) HarmoniseObjectFactory
1346: .instantiateHarmoniseObject(
1347: m_dsi,
1348: Template.class.getName(),
1349: Integer
1350: .parseInt(subEl
1351: .getAttribute(AbstractObject.ATTRIB_ID)));
1352:
1353: condEl.appendChild(pobj.publish(tmplt,
1354: output, state));
1355: } catch (HarmoniseFactoryException e) {
1356: // do nothing - just doesn't figure in conditions
1357: m_logger.log(Level.WARNING, e
1358: .getLocalizedMessage(), e);
1359: } catch (NumberFormatException e) {
1360: throw new PublishException(e);
1361: }
1362: } else if (subEl
1363: .getTagName()
1364: .equalsIgnoreCase(
1365: AbstractPropertyInstance.TAG_PROPERTYINSTANCE)) {
1366:
1367: AbstractPropertyInstance pobj = null;
1368:
1369: try {
1370: pobj = PropertyInstanceFactory
1371: .getPropertyInstance(m_dsi, subEl);
1372: } catch (DataAccessException e) {
1373: throw new PublishException(
1374: "Error occurred while populating property instance:",
1375: e);
1376: } catch (HarmoniseFactoryException e) {
1377: throw new PublishException(
1378: "Error occurred while getting property instance from factory:",
1379: e);
1380: }
1381:
1382: try {
1383: pobj.populate(subEl, state);
1384: } catch (PopulateException e) {
1385: throw new PublishException(
1386: "Populate exception", e);
1387: }
1388: condEl.appendChild(pobj.publish(subEl, output,
1389: state));
1390: } else {
1391: condEl.appendChild(output.copyNode(subEl));
1392: }
1393: }
1394:
1395: try {
1396: populateConditionsFromState(condEl, output, state);
1397: } catch (PopulateException e) {
1398: throw new PublishException("Populate exception", e);
1399: }
1400: newSearch.appendChild(condEl);
1401: } else if (sTagName.equalsIgnoreCase(TAG_SUBMIT)) {
1402: newSearch.appendChild(output.copyNode(elTemp));
1403: }
1404: }
1405:
1406: return newSearch;
1407: }
1408:
1409: /**
1410: * Populates the search with filter conditions found in
1411: * <code>xmlElement</code>.
1412: *
1413: * @param xmlElement
1414: * @throws PublishException
1415: */
1416: protected void processFilterConditions(Element xmlElement)
1417: throws PublishException {
1418: if (xmlElement.getTagName().equals(TAG_FILTERCONDITIONS) == false) {
1419: throw new InvalidXMLElementException("Expecting "
1420: + TAG_FILTERCONDITIONS + " got "
1421: + xmlElement.getTagName());
1422: }
1423:
1424: NodeList propertyEls = xmlElement
1425: .getElementsByTagName(Property.TAG_PROPERTY);
1426:
1427: if (propertyEls.getLength() > 0) {
1428: m_filterProps = new Vector(16);
1429: }
1430:
1431: for (int i = 0; i < propertyEls.getLength(); i++) {
1432: Element propertyElement = (Element) propertyEls.item(0);
1433: NodeList pathNL = propertyElement
1434: .getElementsByTagName(AbstractChildObject.TAG_PATH);
1435:
1436: if (pathNL.getLength() > 0) {
1437:
1438: try {
1439: Property prop = (Property) HarmoniseObjectFactory
1440: .instantiateHarmoniseObject(
1441: m_dsi,
1442: Property.class.getName(),
1443: XMLDocument
1444: .getChildTextNodeValue((Element) pathNL
1445: .item(0)));
1446: m_filterProps.add(prop);
1447: } catch (HarmoniseFactoryException e) {
1448: throw new PublishException("Factory exception", e);
1449: }
1450:
1451: }
1452:
1453: }
1454:
1455: NodeList filterSourceEls = xmlElement
1456: .getElementsByTagName(TAG_FILTERSOURCE);
1457:
1458: if (filterSourceEls.getLength() > 0) {
1459: Element elFilterSource = (Element) filterSourceEls.item(0)
1460: .getFirstChild();
1461: m_sFilterObjectClassname = elFilterSource.getTagName();
1462: }
1463: }
1464:
1465: /**
1466: * Adds conditions to the search based on the filter source found in the
1467: * <code>State</code>. Given a set of property instances specified in
1468: * <code>xmlElement</code>, the filter source object is located and
1469: * values for the conditions are taken for the conditions.
1470: *
1471: * @param xmlElement
1472: * @param state
1473: * @throws PublishException
1474: */
1475: protected void addFilterSourceConditions(Element xmlElement,
1476: State state) throws PublishException {
1477: Profile filterProfile = createFilterConditionsProfile(
1478: xmlElement, state);
1479:
1480: try {
1481: List props = filterProfile.getPropertyInstances();
1482:
1483: if (props.size() > 0) {
1484: for (int i = 0; i < props.size(); i++) {
1485: addConditionProperty((AbstractPropertyInstance) props
1486: .get(i));
1487: }
1488: } else {
1489: m_bFilterCondsNotFound = true;
1490: }
1491: } catch (DataAccessException e) {
1492: throw new PublishException(
1493: "Error occured getting properties from profile", e);
1494: }
1495: }
1496:
1497: /**
1498: * Processes a 'Conditions' element to extract the conditions to be used in
1499: * the search.
1500: *
1501: * @param xmlElement
1502: * @param state
1503: * @throws PublishException
1504: */
1505: protected void processSearchConditions(Element xmlElement,
1506: State state) throws PublishException {
1507: if (xmlElement.getTagName().equals(TAG_CONDITIONS) == false) {
1508: throw new InvalidXMLElementException("Expected "
1509: + TAG_CONDITIONS + " got "
1510: + xmlElement.getTagName());
1511: }
1512:
1513: NodeList nodes = xmlElement.getChildNodes();
1514:
1515: for (int i = 0; i < nodes.getLength(); i++) {
1516: if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
1517: continue;
1518: }
1519:
1520: Element condEl = (Element) nodes.item(i);
1521: String sTagName = condEl.getTagName();
1522:
1523: try {
1524:
1525: if (sTagName
1526: .equalsIgnoreCase(AbstractChildObject.TAG_GROUP)) {
1527: Element groupEl = (Element) condEl
1528: .getElementsByTagName("*").item(0);
1529: AbstractParentObject grpObj = (AbstractParentObject) HarmoniseObjectFactory
1530: .instantiatePublishableObject(this .m_dsi,
1531: groupEl, state);
1532:
1533: if (grpObj != null) {
1534: addConditionGroup(grpObj);
1535:
1536: if (condEl.getAttribute(ATTRIB_SUB)
1537: .equalsIgnoreCase("true")) {
1538: addSubGroupsAsConditions(grpObj);
1539: }
1540: } else if (m_logger.isLoggable(Level.INFO)) {
1541: m_logger.logp(Level.INFO, this .getClass()
1542: .getName(), "processSearchConditions",
1543: "Group for group condition not found");
1544: }
1545:
1546: } else if (sTagName.equalsIgnoreCase(TAG_POSITION)) {
1547: m_nPosition = Integer.parseInt(XMLDocument
1548: .getChildTextNodeValue(condEl));
1549: } else if (sTagName
1550: .equalsIgnoreCase(AbstractPropertyInstance.TAG_PROPERTYINSTANCE)) {
1551: AbstractPropertyInstance propInst = PropertyInstanceFactory
1552: .getPropertyInstance(m_dsi, condEl);
1553:
1554: propInst.populate(condEl, state);
1555:
1556: addConditionProperty(propInst);
1557:
1558: } else if (sTagName
1559: .equalsIgnoreCase(AbstractEditableObject.TAG_STATUS)) {
1560: String txt = XMLDocument
1561: .getChildTextNodeValue(condEl);
1562:
1563: if (txt.equals(Status.APPROVED.getStringValue())) {
1564: this .m_bApprovedSearch = true;
1565: } else if (txt.equals(Status.UNAPPROVED
1566: .getStringValue())) {
1567: this .m_bApprovedSearch = false;
1568: } else {
1569: //if txt is a integer then it may well be a valid
1570: // status code
1571: try {
1572: int nStatus = Integer.parseInt(txt);
1573:
1574: if (nStatus == 0) {
1575: this .m_bApprovedSearch = true;
1576: }
1577:
1578: if (nStatus == 1) {
1579: this .m_bApprovedSearch = false;
1580: }
1581: } catch (NumberFormatException numexp) {
1582: m_logger.log(Level.WARNING, numexp
1583: .getLocalizedMessage(), numexp);
1584: }
1585: }
1586: } else {
1587: addWhereConditionsFromXML(condEl, state);
1588: }
1589: } catch (NumberFormatException e) {
1590: throw new PublishException("Number format error", e);
1591: } catch (HarmoniseFactoryException e) {
1592: throw new PublishException("Factory error", e);
1593: } catch (DataAccessException e) {
1594: throw new PublishException("data access error", e);
1595: } catch (PopulateException e) {
1596: throw new PublishException("populate error", e);
1597: } catch (DataStoreException e) {
1598: throw new PublishException("data store error", e);
1599: }
1600: }
1601: }
1602:
1603: /**
1604: * Sets the text associated with this search.
1605: *
1606: * @param sSearchText
1607: */
1608: protected void setSearchText(String sSearchText) {
1609: m_sSearchText = sSearchText;
1610: }
1611:
1612: /**
1613: * Returns the text associated with this search
1614: *
1615: * @return
1616: */
1617: protected String getSearchText() {
1618: return m_sSearchText;
1619: }
1620:
1621: /*-------------------------------------------------------------------
1622: Private methods
1623: ------------------------------------------------------------------*/
1624:
1625: /**
1626: * Sets the object type that the search will be conducted on, based on the
1627: * object type associated with the given <code>Element</code>.
1628: *
1629: * @param sSearchObjEl
1630: * @throws SearchException
1631: * @throws DataStoreException
1632: * @throws PopulateException
1633: */
1634: private void setSearchType(Element sSearchObjEl)
1635: throws SearchException, DataStoreException,
1636: PopulateException {
1637: try {
1638: m_searchObject = (DataStoreObject) HarmoniseObjectFactory
1639: .instantiatePublishableObject(this .m_dsi,
1640: sSearchObjEl, null);
1641: } catch (HarmoniseFactoryException e) {
1642: throw new SearchException("Factory error", e);
1643: }
1644:
1645: m_sSearchType = sSearchObjEl.getTagName();
1646:
1647: ColumnRef colrefId = m_searchObject.getInstanceColumnRef(
1648: AbstractObject.ATTRIB_ID,
1649: ((AbstractObject) m_searchObject).isHistorical());
1650:
1651: if (colrefId != null) {
1652: addSelectColumn(colrefId);
1653: }
1654:
1655: NamedNodeMap nnm = sSearchObjEl.getAttributes();
1656:
1657: //handle attributes
1658: for (int i = 0; i < nnm.getLength(); i++) {
1659: Attr attribute = (Attr) nnm.item(i);
1660:
1661: String sName = attribute.getName();
1662: String sValue = attribute.getValue();
1663:
1664: if ((sValue != null) && (sValue.length() > 0)) {
1665: Vector vec = new Vector();
1666: vec.add(sValue);
1667:
1668: try {
1669: this .addConditionColumn(m_searchObject
1670: .getInstanceColumnRef(sName,
1671: ((AbstractObject) m_searchObject)
1672: .isHistorical()), "=", vec);
1673: } catch (InvalidColumnReferenceException e) {
1674: m_logger.log(Level.INFO, e.getLocalizedMessage());
1675: }
1676: }
1677: }
1678:
1679: //add select columns from elements
1680: NodeList nodes = sSearchObjEl.getChildNodes();
1681:
1682: for (int i = 0; i < nodes.getLength(); i++) {
1683: if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
1684: continue;
1685: }
1686:
1687: Element el = (Element) nodes.item(i);
1688: String sTagName = el.getNodeName();
1689:
1690: if (sTagName.equals(Profile.TAG_PROFILE) == true) {
1691: NodeList propInstNodes = el
1692: .getElementsByTagName(AbstractPropertyInstance.TAG_PROPERTYINSTANCE);
1693:
1694: for (int j = 0; j < propInstNodes.getLength(); j++) {
1695: Element propInstEl = (Element) propInstNodes
1696: .item(j);
1697: NodeList propNodes = propInstEl
1698: .getElementsByTagName(Property.TAG_PROPERTY);
1699: AbstractPropertyInstance propInst = null;
1700: Element propEl = null;
1701: for (int k = 0; k < propNodes.getLength(); k++) {
1702: propEl = (Element) propNodes.item(k);
1703: if (propEl.hasAttribute(ATTRIB_ORDER_DIRECTION)
1704: && propEl.getAttribute(
1705: ATTRIB_ORDER_DIRECTION)
1706: .length() > 0) {
1707: Element nameEl = XMLUtils
1708: .getFirstNamedChild(propEl,
1709: Property.TAG_NAME);
1710: try {
1711: if (nameEl != null) {
1712: String sPropName = XMLUtils
1713: .getChildTextValue(nameEl);
1714: Property prop = PropertyFactory
1715: .getPropertyFromName(m_dsi,
1716: sPropName);
1717: propInst = PropertyInstanceFactory
1718: .getPropertyInstance(m_dsi,
1719: prop);
1720: propInst.populate(propEl, null);
1721:
1722: addSelectProperty(propInst);
1723:
1724: String sOrderDirection = propEl
1725: .getAttribute(ATTRIB_ORDER_DIRECTION);
1726:
1727: setOrderBy(propInst,
1728: sOrderDirection);
1729: break;
1730: }
1731: } catch (DataAccessException e) {
1732: throw new PopulateException(
1733: "Error populating property instance: ",
1734: e);
1735: } catch (HarmoniseFactoryException e) {
1736: throw new PopulateException(
1737: "Error getting property instance from factory: ",
1738: e);
1739: }
1740: }
1741: }
1742: }
1743: } else if (sTagName
1744: .equals(AbstractParentObject.TAG_CHILDREN)
1745: || sTagName
1746: .equals(AbstractParentObject.TAG_SUBGROUPS)
1747: || sTagName.equals(AbstractParentObject.TAG_GROUP)) {
1748: /**
1749: * @todo these tags are not handled in the contruction of the
1750: * Sql
1751: */
1752: } else {
1753: String sLoopTagName = sTagName;
1754: Element loopEl = el;
1755: ColumnRef colref = null;
1756:
1757: while ((sLoopTagName != null) && (colref == null)) {
1758: try {
1759: colref = m_searchObject.getInstanceColumnRef(
1760: sLoopTagName,
1761: ((AbstractObject) m_searchObject)
1762: .isHistorical());
1763: if (loopEl.hasAttribute(ATTRIB_ORDER_DIRECTION)) {
1764: String sOrderDirection = loopEl
1765: .getAttribute(ATTRIB_ORDER_DIRECTION);
1766:
1767: if (sOrderDirection.length() > 0) {
1768: setOrderBy(colref, sOrderDirection);
1769: }
1770: }
1771: } catch (InvalidColumnReferenceException e) {
1772: NodeList loopNodes = loopEl
1773: .getElementsByTagName("*");
1774:
1775: if (loopNodes.getLength() > 0) {
1776: loopEl = (Element) loopNodes.item(0);
1777: sLoopTagName = loopEl.getTagName();
1778:
1779: } else {
1780: sLoopTagName = null;
1781: }
1782: }
1783: }
1784:
1785: if (colref != null) {
1786: this .addSelectColumn(colref);
1787: }
1788: }
1789: }
1790: }
1791:
1792: /**
1793: * Returns a <code>String</code> containing a query for the search to be
1794: * run against the indexer.
1795: *
1796: * @return
1797: * @throws HarmoniseIndexerException
1798: * @throws DataStoreException
1799: */
1800: private String getIndexSearchQuery()
1801: throws HarmoniseIndexerException, DataStoreException {
1802: Vector groupIds = new Vector(16);
1803: HarmoniseIndexer indexer = HarmoniseIndexer.getInstance();
1804: String sName = null;
1805: String sDisplayName = null;
1806: String sSummary = null;
1807: String sContents = null;
1808: String sIndexerQuery = "";
1809:
1810: for (int i = 0; i < this .m_ConditionGroups.size(); i++) {
1811: int groupId = ((AbstractParentObject) m_ConditionGroups
1812: .get(i)).getId();
1813: groupIds.addElement(String.valueOf(groupId));
1814: }
1815:
1816: Vector conditions2remove = new Vector();
1817:
1818: for (int i = 0; i < this .m_ConditionColumns.size(); i++) {
1819: WhereCondition where = (WhereCondition) m_ConditionColumns
1820: .get(i);
1821:
1822: String columnref = where.getFullColumnRef();
1823: Object oText = ((Vector) where.getValues()).firstElement();
1824:
1825: if (columnref.equalsIgnoreCase(this .m_searchObject
1826: .getInstanceColumnRef(
1827: AbstractObject.TAG_NAME,
1828: ((AbstractObject) m_searchObject)
1829: .isHistorical()).getFullRef())) {
1830: sName = (String) oText;
1831: conditions2remove.addElement(where);
1832: m_bIndexableSearch = true;
1833: } else if (columnref.equalsIgnoreCase(this .m_searchObject
1834: .getInstanceColumnRef(
1835: AbstractEditableObject.TAG_DISPLAY_NAME,
1836: ((AbstractObject) m_searchObject)
1837: .isHistorical()).getFullRef())) {
1838: sDisplayName = (String) oText;
1839: conditions2remove.addElement(where);
1840: m_bIndexableSearch = true;
1841: } else if (columnref.equalsIgnoreCase(this .m_searchObject
1842: .getInstanceColumnRef(
1843: AbstractObject.TAG_SUMMARY,
1844: ((AbstractObject) m_searchObject)
1845: .isHistorical()).getFullRef())) {
1846: sSummary = (String) oText;
1847: conditions2remove.addElement(where);
1848: m_bIndexableSearch = true;
1849: } else if (this .m_searchObject instanceof org.openharmonise.rm.resources.content.Document
1850: && columnref
1851: .equalsIgnoreCase(this .m_searchObject
1852: .getInstanceColumnRef(
1853: org.openharmonise.rm.resources.content.Document.TAG_CONTENT,
1854: ((AbstractObject) m_searchObject)
1855: .isHistorical())
1856: .getFullRef())) {
1857: sContents = (String) oText;
1858: conditions2remove.addElement(where);
1859: m_bIndexableSearch = true;
1860: }
1861: }
1862:
1863: if (m_bIndexableSearch == true) {
1864: //remove appropriate conditions
1865: this .m_ConditionGroups.clear();
1866:
1867: for (int i = 0; i < conditions2remove.size(); i++) {
1868: this .m_ConditionColumns.remove(conditions2remove
1869: .elementAt(i));
1870: }
1871:
1872: //only fill query string if all of the fields are present but not
1873: // empty
1874: if ((sName != null && sName.length() > 0)
1875: || (sSummary != null && sSummary.length() > 0)
1876: || (sContents != null && sContents.length() > 0)
1877: || (sDisplayName != null && sDisplayName.length() > 0)) {
1878: sIndexerQuery = indexer.getQuery(m_searchObject
1879: .getClass(), groupIds, sName, sDisplayName,
1880: sSummary, sContents);
1881: }
1882: }
1883:
1884: return sIndexerQuery;
1885: }
1886:
1887: /**
1888: * Populates conditions by processing the XML contained in the given
1889: * <code>State</code>.
1890: *
1891: * @param search
1892: * @param output
1893: * @param state
1894: * @throws PublishException
1895: * @throws PopulateException
1896: */
1897: private void populateConditionsFromState(Element search,
1898: HarmoniseOutput output, State state)
1899: throws PublishException, PopulateException {
1900: Element stateSearch = state.findElement(search);
1901: Vector nodes2Remove = new Vector(16);
1902:
1903: if (stateSearch != null) {
1904: NodeList nodes = search.getChildNodes();
1905:
1906: //take value here before we start adding nodes
1907: int nIter = nodes.getLength();
1908:
1909: for (int i = 0; i < nIter; i++) {
1910: Element tempEl = (Element) nodes.item(i);
1911: String sTagName = tempEl.getTagName();
1912:
1913: if (tempEl.getNodeType() != Node.ELEMENT_NODE) {
1914: continue;
1915: }
1916:
1917: if (sTagName
1918: .equalsIgnoreCase(AbstractChildObject.TAG_GROUP)) {
1919: NodeList stateGroups = state.getDocumentElement()
1920: .getElementsByTagName(
1921: AbstractChildObject.TAG_GROUP);
1922:
1923: if (stateGroups.getLength() > 0) {
1924: Element stateGroupEl = (Element) stateGroups
1925: .item(0);
1926: tempEl.setAttribute(ATTRIB_SUB, stateGroupEl
1927: .getAttribute(ATTRIB_SUB));
1928:
1929: NodeList groupNodes = stateGroupEl
1930: .getChildNodes();
1931:
1932: for (int j = 0; j < groupNodes.getLength(); j++) {
1933: Element groupEl = (Element) groupNodes
1934: .item(j);
1935: Element foundEl = XMLDocument.findElement(
1936: tempEl, groupEl);
1937:
1938: if (foundEl != null) {
1939: foundEl.setAttribute(ATTRIB_SELECTED,
1940: "selected");
1941: }
1942: }
1943: }
1944: } else {
1945: Element foundEl = XMLDocument.findElement(
1946: stateSearch, tempEl);
1947:
1948: //if element is in state then we can use data to
1949: // instantiate object then publish as new
1950: //element to replace current element in searchconditions
1951: if ((foundEl != null)
1952: && ((Element) foundEl.getParentNode())
1953: .getTagName().equalsIgnoreCase(
1954: TAG_CONDITIONS)) {
1955: if (sTagName
1956: .equalsIgnoreCase(AbstractPropertyInstance.TAG_PROPERTYINSTANCE)) {
1957: //only do anything of propinst has values
1958: // associated to it
1959: if (foundEl.getChildNodes().getLength() > 0) {
1960: try {
1961: Publishable pubObj = HarmoniseObjectFactory
1962: .instantiatePublishableObject(
1963: this .m_dsi, tempEl,
1964: state);
1965:
1966: pubObj.populate(foundEl, state);
1967:
1968: Element newEl = pubObj.publish(
1969: tempEl, output, state);
1970:
1971: nodes2Remove.add(tempEl);
1972: search.appendChild(newEl);
1973: } catch (HarmoniseFactoryException e) {
1974: throw new PopulateException(
1975: "Factory error", e);
1976: }
1977: }
1978: } else {
1979: nodes2Remove.add(tempEl);
1980:
1981: Element copyEl = (Element) output
1982: .copyNode(foundEl);
1983: output.copyChildren(copyEl, tempEl);
1984: copyEl.setAttribute(ATTRIB_SELECTED,
1985: ATTRIB_SELECTED);
1986: search.appendChild(copyEl);
1987: }
1988: }
1989: }
1990: }
1991:
1992: for (int i = 0; i < nodes2Remove.size(); i++) {
1993: search.removeChild((Element) nodes2Remove.elementAt(i));
1994: }
1995: }
1996: }
1997:
1998: /**
1999: * Processes <code>xmlElement</code> to add 'where' conditions to the
2000: * search.
2001: *
2002: * @param xmlElement
2003: * @param state
2004: * @throws DataStoreException
2005: * @throws HarmoniseFactoryException
2006: */
2007: private void addWhereConditionsFromXML(Element xmlElement,
2008: State state) throws DataStoreException,
2009: HarmoniseFactoryException {
2010: String sTagName = xmlElement.getTagName();
2011: String sOperator = xmlElement
2012: .getAttribute(AbstractPropertyInstance.ATTRIB_OPERATOR);
2013:
2014: if (sOperator == null) {
2015: sOperator = "=";
2016: }
2017:
2018: //first assume that we're dealing with a some searchobject data
2019: Vector tempVec = new Vector();
2020: String txt = XMLDocument.getChildTextNodeValue(xmlElement);
2021:
2022: ColumnRef colref = null;
2023:
2024: colref = this .m_searchObject.getInstanceColumnRef(xmlElement
2025: .getTagName(), ((AbstractObject) m_searchObject)
2026: .isHistorical());
2027:
2028: if (colref != null) {
2029: if ((txt != null) && (txt.length() > 0)) {
2030: tempVec.add(txt);
2031:
2032: WhereCondition where = new WhereCondition(colref,
2033: sOperator, tempVec);
2034: m_ConditionColumns.add(where);
2035: }
2036: } else {
2037: DataStoreObject dsObj = (DataStoreObject) HarmoniseObjectFactory
2038: .instantiatePublishableObject(this .m_dsi,
2039: xmlElement, state);
2040:
2041: NodeList children = xmlElement.getChildNodes();
2042:
2043: for (int i = 0; i < children.getLength(); i++) {
2044: if (children.item(i).getNodeType() != Node.ELEMENT_NODE) {
2045: continue;
2046: }
2047:
2048: Element tempEl = (Element) children.item(i);
2049:
2050: if (tempVec == null) {
2051: tempVec = new Vector();
2052: }
2053:
2054: tempVec.clear();
2055: tempVec.add(XMLDocument.getChildTextNodeValue(tempEl));
2056:
2057: WhereCondition where = new WhereCondition(dsObj
2058: .getInstanceColumnRef(tempEl.getTagName(),
2059: ((AbstractObject) m_searchObject)
2060: .isHistorical()), sOperator,
2061: tempVec);
2062: m_ConditionColumns.add(where);
2063: }
2064:
2065: }
2066: }
2067:
2068: /**
2069: * Returns a 'FurtherLink' element with the given link text, page id, and
2070: * position with in the results.
2071: *
2072: * @param output
2073: * @param linktext
2074: * @param nPosition
2075: * @param nPageId
2076: * @return
2077: */
2078: private Element createFurtherLinkElement(HarmoniseOutput output,
2079: String linktext, int nPosition, int nPageId) {
2080: Element xnLink = output.createElement(WebPage.TAG_LINK);
2081:
2082: Element xnLinkPage = output.createElement(WebPage.TAG_PAGE);
2083:
2084: xnLinkPage.setAttribute(WebPage.ATTRIB_ID, Integer
2085: .toString(nPageId));
2086:
2087: Node xnLinkTxt = output.createElement(WebPage.TAG_LINK_TEXT);
2088: Text txt = output.createTextNode(linktext);
2089:
2090: // Profile to carry search through Prev link
2091: Element xnState = output.createElement(State.TAG_STATE);
2092:
2093: Element xnCond = output.createElement(TAG_CONDITIONS);
2094: xnState.appendChild(xnCond);
2095:
2096: Element xnPosition = output.createElement(TAG_POSITION);
2097:
2098: Text txtPos = output
2099: .createTextNode(Integer.toString(nPosition));
2100:
2101: xnPosition.appendChild(txtPos);
2102: xnCond.appendChild(xnPosition);
2103: xnLink.appendChild(xnState);
2104:
2105: xnLink.appendChild(xnLinkPage);
2106:
2107: xnLinkTxt.appendChild(txt);
2108: xnLink.appendChild(xnLinkTxt);
2109:
2110: return xnLink;
2111: }
2112:
2113: /**
2114: * Returns a <code>Profile</code> which represents the
2115: * <code>xmlElement</code> 'FilterCondition' element.
2116: *
2117: * @param xmlElement
2118: * @param state
2119: * @return @throws
2120: * PublishException
2121: */
2122: private Profile createFilterConditionsProfile(Element xmlElement,
2123: State state) throws PublishException {
2124: if (xmlElement.getTagName().equals(TAG_FILTERCONDITIONS) == false) {
2125: throw new InvalidXMLElementException("Expecting "
2126: + TAG_FILTERCONDITIONS + " got "
2127: + xmlElement.getTagName());
2128: }
2129:
2130: String sInclusive = xmlElement.getAttribute(ATTRIB_INCLUSIVE);
2131:
2132: if ((sInclusive != null) && sInclusive.equalsIgnoreCase("true")) {
2133: m_bFilterCondsInclusive = true;
2134: }
2135:
2136: Profile returnProf = null;
2137: Profile filterObjectProfile = null;
2138: AbstractProfiledObject filterObject = null;
2139:
2140: NodeList childNodes = xmlElement.getChildNodes();
2141:
2142: for (int i = 0; i < childNodes.getLength(); i++) {
2143: if (childNodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
2144: continue;
2145: }
2146:
2147: Element childEl = (Element) childNodes.item(i);
2148: String sTagName = childEl.getTagName();
2149:
2150: try {
2151:
2152: if (sTagName.equalsIgnoreCase(TAG_FILTERSOURCE)) {
2153: NodeList sourceNodes = childEl.getChildNodes();
2154:
2155: for (int j = 0; j < sourceNodes.getLength(); j++) {
2156: if (sourceNodes.item(j).getNodeType() != Node.ELEMENT_NODE) {
2157: continue;
2158: }
2159:
2160: Element elFilterSource = (Element) sourceNodes
2161: .item(j);
2162: String sFilterObjectClassname = elFilterSource
2163: .getTagName();
2164:
2165: filterObject = (AbstractProfiledObject) HarmoniseObjectFactory
2166: .instantiateHarmoniseObject(m_dsi,
2167: elFilterSource, state);
2168: filterObjectProfile = filterObject.getProfile();
2169: }
2170: } else if (sTagName.equalsIgnoreCase(TAG_OR)) {
2171: m_ConditionOperator = "OR";
2172: } else if (sTagName
2173: .equalsIgnoreCase(AbstractPropertyInstance.TAG_PROPERTYINSTANCE)
2174: || sTagName
2175: .equalsIgnoreCase(Property.TAG_PROPERTY)) {
2176: AbstractPropertyInstance tmpPropInst = PropertyInstanceFactory
2177: .getPropertyInstance(m_dsi, childEl/*
2178: * , returnProf
2179: */);
2180:
2181: tmpPropInst.populate(childEl, state);
2182:
2183: //if property tag doesn't have values then take property
2184: // condition from filter source
2185: if (tmpPropInst.hasValues() == false) {
2186: if (filterObjectProfile != null) {
2187: AbstractPropertyInstance fltrSrcPropInst = filterObjectProfile
2188: .getPropertyInstance(tmpPropInst
2189: .getProperty());
2190:
2191: if (fltrSrcPropInst != null) {
2192: if (returnProf == null) {
2193: returnProf = new Profile(m_dsi,
2194: filterObject);
2195: }
2196:
2197: returnProf
2198: .addPropertyInstance(fltrSrcPropInst);
2199: }
2200:
2201: //TODO need to handle situation where filter object profile does
2202: //not contain the property, currently errors - might lose operator for property
2203: //need to review this - need to think
2204: //about exclusivity wrt to this issue
2205:
2206: }
2207: } else {
2208: returnProf.addPropertyInstance(tmpPropInst);
2209: }
2210: }
2211: } catch (ProfileException e) {
2212: throw new PublishException("Profile error", e);
2213: } catch (DataAccessException e) {
2214: throw new PublishException("Data access error", e);
2215: } catch (HarmoniseFactoryException e) {
2216: throw new PublishException("Factory error", e);
2217: } catch (PopulateException e) {
2218: throw new PublishException("Population error", e);
2219: }
2220: }
2221:
2222: return returnProf;
2223: }
2224:
2225: /**
2226: * Adds 'where' conditions to the select statement from the condition data
2227: * contained in this object.
2228: *
2229: * @param select
2230: * @throws DataAccessException
2231: * @throws DataStoreException
2232: */
2233: private void addWhereConditions(SelectStatement select)
2234: throws DataAccessException, DataStoreException {
2235:
2236: SelectStatement subselect = null;
2237:
2238: if ((m_ConditionProfile.size() > 0)
2239: || (m_ConditionGroups.size() > 0)) {
2240: subselect = new SelectStatement();
2241:
2242: subselect.setDistinct(true);
2243: subselect.addSelectColumn(m_searchObject
2244: .getInstanceColumnRef(AbstractObject.ATTRIB_ID,
2245: ((AbstractObject) m_searchObject)
2246: .isHistorical()));
2247: }
2248:
2249: //are we going to do a strict search by type or just return all
2250: //matching objects from the same table, e.g. if class B was a
2251: //subclass of class A are doing a search on all objects of
2252: //class A or specifically class B, if so add the appropriate
2253: //condition
2254: if (m_bStrictType == true) {
2255: if (subselect != null) {
2256: subselect
2257: .addWhereCondition(
2258: ((AbstractObject) this .m_searchObject)
2259: .getInstanceColumnRef(
2260: Search.ATTRIB_OBJECT_TYPE,
2261: ((AbstractObject) this .m_searchObject)
2262: .isHistorical()),
2263: "=",
2264: ((AbstractObject) this .m_searchObject)
2265: .getType());
2266: } else {
2267: select
2268: .addWhereCondition(
2269: ((AbstractObject) this .m_searchObject)
2270: .getInstanceColumnRef(
2271: Search.ATTRIB_OBJECT_TYPE,
2272: ((AbstractObject) this .m_searchObject)
2273: .isHistorical()),
2274: "=",
2275: ((AbstractObject) this .m_searchObject)
2276: .getType());
2277: }
2278: }
2279:
2280: if (m_searchObject instanceof AbstractProfiledObject) {
2281: AbstractProfiledObject profObj = (AbstractProfiledObject) m_searchObject;
2282:
2283: //add conditions needed for those property instances to be returned
2284: //in select statement
2285: addSelectPropertyInstanceConditions(select);
2286:
2287: if (m_searchObject instanceof AbstractChildObject) {
2288: //add relationship conditions
2289: addGroupConditions(subselect);
2290: }
2291:
2292: //add property instance conditions
2293: addPropertyInstanceConditions(subselect);
2294: }
2295:
2296: //if this search is on live objects only
2297: if (m_bApprovedSearch == true) {
2298: Vector tempVec = new Vector();
2299: tempVec.add(new Integer(Status.APPROVED.getIntValue()));
2300:
2301: WhereCondition where = new WhereCondition(m_searchObject
2302: .getInstanceColumnRef(
2303: AbstractEditableObject.TAG_STATUS,
2304: ((AbstractObject) this .m_searchObject)
2305: .isHistorical()), "=", tempVec);
2306: m_ConditionColumns.add(where);
2307: }
2308:
2309: //add core data conditions
2310: if (subselect != null) {
2311: addCoreDataConditions(subselect);
2312: } else {
2313: addCoreDataConditions(select);
2314: }
2315:
2316: //add nested select statement
2317: if (subselect != null) {
2318: WhereCondition whereSubselect = new WhereCondition(
2319: m_searchObject.getInstanceColumnRef(
2320: AbstractObject.ATTRIB_ID,
2321: ((AbstractObject) this .m_searchObject)
2322: .isHistorical()), "IN", subselect);
2323: select.addWhereCondition(whereSubselect);
2324: }
2325: }
2326:
2327: /**
2328: * Adds relationship conditions to the select statement based on conditions
2329: * held with in this search object.
2330: *
2331: * @param subselect
2332: * @throws DataStoreException
2333: */
2334: private void addGroupConditions(SelectStatement subselect)
2335: throws DataStoreException {
2336: if (m_ConditionGroups.size() > 0) {
2337:
2338: if (m_searchObject instanceof AbstractChildObject
2339: && ((AbstractChildObject) m_searchObject)
2340: .isHistorical() == true) {
2341: WhereConditionGroup wheres = new WhereConditionGroup();
2342: wheres.setStringingOperator("or");
2343:
2344: for (int i = 0; i < m_ConditionGroups.size(); i++) {
2345: AbstractParentObject grpObj = (AbstractParentObject) m_ConditionGroups
2346: .get(i);
2347:
2348: try {
2349: wheres.addCondition(m_searchObject
2350: .getInstanceColumnRef(
2351: AbstractChildObject.TAG_PATH,
2352: true), "STARTS_WITH", grpObj
2353: .getPath());
2354: } catch (DataAccessException e) {
2355: throw new DataStoreException(e);
2356: }
2357: }
2358:
2359: subselect.addWhereCondition(wheres);
2360: } else if (this .m_searchObject instanceof AbstractParentObject) {
2361: WhereConditionGroup wheres = new WhereConditionGroup();
2362: String sGroupAlias = "grp";
2363: String sGroupTableName = "";
2364: wheres.setStringingOperator("or");
2365:
2366: DataStoreObject dsObj = null;
2367: ColumnRef colId = m_searchObject.getInstanceColumnRef(
2368: AbstractObject.ATTRIB_ID, false);
2369: sGroupTableName = colId.getTable();
2370: colId.setTable(sGroupAlias);
2371:
2372: for (int i = 0; i < m_ConditionGroups.size(); i++) {
2373: dsObj = (DataStoreObject) m_ConditionGroups.get(i);
2374:
2375: wheres.addCondition(colId, "=", dsObj.getId());
2376: }
2377:
2378: subselect.addWhereCondition(wheres);
2379:
2380: ColumnRef subJoinKey = m_searchObject
2381: .getInstanceColumnRef(
2382: AbstractParentObject.TAG_SUBGROUPS,
2383: false);
2384: ColumnRef subKey = m_searchObject.getInstanceColumnRef(
2385: AbstractObject.ATTRIB_KEY, false);
2386: ColumnRef parentJoinKey = m_searchObject
2387: .getInstanceColumnRef(
2388: AbstractParentObject.TAG_GROUP, false);
2389: ColumnRef parentKey = m_searchObject
2390: .getInstanceColumnRef(
2391: AbstractObject.ATTRIB_KEY, false);
2392: parentKey.setTable(sGroupAlias);
2393:
2394: subselect.addJoinCondition(parentJoinKey, parentKey);
2395: subselect.addJoinCondition(subJoinKey, subKey);
2396:
2397: subselect.addTableAlias(sGroupTableName, sGroupAlias);
2398: } else {
2399: WhereConditionGroup wheres = new WhereConditionGroup();
2400: wheres.setStringingOperator("or");
2401:
2402: DataStoreObject dsObj = null;
2403:
2404: for (int i = 0; i < m_ConditionGroups.size(); i++) {
2405: dsObj = (DataStoreObject) m_ConditionGroups.get(i);
2406: wheres.addCondition(dsObj.getInstanceColumnRef(
2407: AbstractObject.ATTRIB_ID, false), "=",
2408: dsObj.getId());
2409: }
2410:
2411: subselect.addWhereCondition(wheres);
2412: subselect.addJoinConditions(dsObj
2413: .getInstanceJoinConditions(this .m_sSearchType,
2414: false));
2415: }
2416: }
2417: }
2418:
2419: /**
2420: * Adds 'join' conditions to the select statement necessary to support the
2421: * return of property instance values in the result set.
2422: *
2423: * @param select
2424: * @throws DataAccessException
2425: * @throws DataStoreException
2426: */
2427: private void addSelectPropertyInstanceConditions(
2428: SelectStatement select) throws DataAccessException,
2429: DataStoreException {
2430: AbstractProfiledObject profObj = (AbstractProfiledObject) m_searchObject;
2431:
2432: if (m_searchObjectProfile == null) {
2433: m_searchObjectProfile = new Profile(m_dsi, profObj);
2434: }
2435: Profile prof = m_searchObjectProfile;
2436:
2437: for (int i = 0; i < this .m_SearchProfile.size(); i++) {
2438: //get necessary object for getting the column refs
2439:
2440: AbstractPropertyInstance condPropInst = (AbstractPropertyInstance) m_SearchProfile
2441: .get(i);
2442: condPropInst.setProfile(prof);
2443:
2444: Property property = condPropInst.getProperty();
2445:
2446: String sPropertyAlias = "spty" + i;
2447: ColumnRef propertyIdCol = property.getInstanceColumnRef(
2448: AbstractObject.ATTRIB_ID, false);
2449: select.addTableAlias(propertyIdCol.getTable(),
2450: sPropertyAlias);
2451: propertyIdCol.setTable(sPropertyAlias);
2452:
2453: ColumnRef propertyNameCol = property.getInstanceColumnRef(
2454: AbstractObject.TAG_NAME, false);
2455: propertyNameCol.setTable(sPropertyAlias);
2456:
2457: //get column refs and set necessary aliases
2458: ColumnRef valColref = condPropInst.getInstanceColumnRef(
2459: AbstractPropertyInstance.TAG_VALUE, false);
2460: String sPropAlias = "sprop" + i;
2461: select.addTableAlias(valColref.getTable(), sPropAlias);
2462: valColref.setTable(sPropAlias);
2463:
2464: ColumnRef dataProfIdColref = condPropInst
2465: .getInstanceColumnRef(Profile.TAG_PROFILE, false);
2466: dataProfIdColref.setTable(sPropAlias);
2467:
2468: ColumnRef dataPropIdColref = condPropInst
2469: .getInstanceColumnRef(Property.TAG_PROPERTY, false);
2470: dataPropIdColref.setTable(sPropAlias);
2471:
2472: ColumnRef profileIdColref = prof.getInstanceColumnRef(
2473: AbstractObject.ATTRIB_ID, prof.isHistorical());
2474:
2475: String sProfAlias = "sprof" + i;
2476:
2477: select
2478: .addTableAlias(profileIdColref.getTable(),
2479: sProfAlias);
2480: profileIdColref.setTable(sProfAlias);
2481:
2482: ColumnRef profNameColref = prof.getInstanceColumnRef(
2483: AbstractObject.TAG_NAME, prof.isHistorical());
2484: profNameColref.setTable(sProfAlias);
2485:
2486: ColumnRef profObjectKeyColref = prof.getInstanceColumnRef(
2487: Profile.ATTRIB_OBJECT_KEY, prof.isHistorical());
2488: profObjectKeyColref.setTable(sProfAlias);
2489:
2490: ColumnRef objectKeyColref = m_searchObject
2491: .getInstanceColumnRef(AbstractObject.ATTRIB_KEY,
2492: ((AbstractObject) m_searchObject)
2493: .isHistorical());
2494:
2495: select.addSelectColumn(profNameColref);
2496: select.addSelectColumn(valColref);
2497:
2498: if ((m_orderByPropMap.isEmpty() == false)
2499: && m_orderByPropMap.containsKey(condPropInst)) {
2500: select.addOrderBy(valColref, (String) m_orderByPropMap
2501: .get(condPropInst));
2502: }
2503:
2504: select.addSelectColumn(propertyIdCol);
2505: select.addSelectColumn(profileIdColref);
2506: select.addSelectColumn(propertyNameCol);
2507:
2508: select.addOuterJoinCondition(dataProfIdColref,
2509: profileIdColref);
2510:
2511: select.addJoinCondition(profObjectKeyColref,
2512: objectKeyColref);
2513:
2514: select.addOuterJoinCondition(dataPropIdColref,
2515: propertyIdCol);
2516: select.addWhereCondition(propertyNameCol, "=", condPropInst
2517: .getName());
2518: }
2519: }
2520:
2521: /**
2522: * Adds the 'where' conditions to the given <code>SelectStatement</code>
2523: * based on the property instance conditions held with in this search object.
2524: *
2525: * @param subselect
2526: * @throws DataStoreException
2527: * @throws DataAccessException
2528: */
2529: private void addPropertyInstanceConditions(SelectStatement subselect)
2530: throws DataStoreException, DataAccessException {
2531: AbstractProfiledObject profObj = (AbstractProfiledObject) m_searchObject;
2532: Profile profObjProf = profObj.getProfile();
2533:
2534: if (m_ConditionProfile.size() > 0) {
2535: //WhereConditions object to hold all the propertyinstance conditions
2536: WhereConditionGroup outerWheres = new WhereConditionGroup();
2537:
2538: for (int i = 0; i < m_ConditionProfile.size(); i++) {
2539: //get necessary object for getting the column refs
2540:
2541: if (m_searchObjectProfile == null) {
2542: m_searchObjectProfile = new Profile(m_dsi, profObj);
2543: }
2544: Profile prof = m_searchObjectProfile;
2545:
2546: AbstractPropertyInstance condPropInst = (AbstractPropertyInstance) m_ConditionProfile
2547: .get(i);
2548:
2549: String sCondOp = condPropInst.getOperator();
2550:
2551: condPropInst.setProfile(prof);
2552:
2553: //if there are no values don't go any further
2554: if (condPropInst.hasValues() == false) {
2555: continue;
2556: }
2557:
2558: if (sCondOp.equals("<>") == false
2559: && sCondOp.equals("!=") == false) {
2560:
2561: addPropertyInstanceWhereCondition(subselect,
2562: outerWheres, i, prof, condPropInst, sCondOp);
2563: } else {
2564: //need to compose a different sort of query for
2565: //the non-existance of a property instance value
2566: //that takes account for profiles which may have
2567: //more than one value for the property instance
2568: //or more than one profile
2569: //or even no profile
2570:
2571: addNonExistentPropertyInstanceCondition(profObj,
2572: outerWheres, prof, condPropInst);
2573: }
2574:
2575: } //end for
2576:
2577: outerWheres.setStringingOperator(m_ConditionOperator);
2578: subselect.addWhereCondition(outerWheres);
2579: }
2580: }
2581:
2582: /**
2583: * Adds a property instance where condition to <code>outerWheres</code>,
2584: * updating <code>subselect</code> with the necessary table aliases.
2585: *
2586: * @param subselect
2587: * @param outerWheres
2588: * @param index
2589: * @param prof
2590: * @param condPropInst
2591: * @param sCondOp
2592: * @throws DataStoreException
2593: * @throws DataAccessException
2594: */
2595: private void addPropertyInstanceWhereCondition(
2596: SelectStatement subselect, WhereConditionGroup outerWheres,
2597: int index, Profile prof,
2598: AbstractPropertyInstance condPropInst, String sCondOp)
2599: throws DataStoreException, DataAccessException {
2600: //set prop inst table alias
2601: String propInstAlias = "prop" + index;
2602:
2603: subselect.addTableAlias(condPropInst.getDBTableName(),
2604: propInstAlias);
2605:
2606: //prof id column in prop inst table
2607: ColumnRef dataProfIdColref = condPropInst.getInstanceColumnRef(
2608: Profile.TAG_PROFILE, false);
2609: dataProfIdColref.setTable(propInstAlias);
2610:
2611: //prop id column in prop inst table
2612: ColumnRef dataPropIdColref = condPropInst.getInstanceColumnRef(
2613: Property.TAG_PROPERTY, false);
2614: dataPropIdColref.setTable(propInstAlias);
2615:
2616: subselect.addWhereCondition(dataPropIdColref, "=", condPropInst
2617: .getProperty().getId());
2618:
2619: //prof id column in profile table
2620: ColumnRef profileIdColref = prof.getInstanceColumnRef(
2621: AbstractObject.ATTRIB_ID, prof.isHistorical());
2622:
2623: //set alias for profile table
2624: String profAlias = "prof" + index;
2625:
2626: subselect.addTableAlias(profileIdColref.getTable(), profAlias);
2627:
2628: profileIdColref.setTable(profAlias);
2629:
2630: //join prop inst table to profile table
2631: subselect.addJoinCondition(dataProfIdColref, profileIdColref);
2632:
2633: ColumnRef profObjectKeyColref = prof.getInstanceColumnRef(
2634: Profile.ATTRIB_OBJECT_KEY, prof.isHistorical());
2635: profObjectKeyColref.setTable(profAlias);
2636:
2637: ColumnRef objectKeyColref = m_searchObject
2638: .getInstanceColumnRef(AbstractObject.ATTRIB_KEY,
2639: ((AbstractObject) m_searchObject)
2640: .isHistorical());
2641:
2642: //join object table to profile table
2643: subselect
2644: .addJoinCondition(profObjectKeyColref, objectKeyColref);
2645:
2646: WhereConditionGroup innerWheres = getPropertyInstanceValueConditions(
2647: condPropInst, sCondOp, propInstAlias);
2648:
2649: if (innerWheres.size() > 1) {
2650: outerWheres.addCondition(innerWheres);
2651: } else {
2652: //no sense in adding a WhereConditions
2653: //when we can just pick up the only condition
2654: //and add it
2655: Object cond = innerWheres.getCondition(0);
2656: if (cond instanceof WhereCondition) {
2657: outerWheres.addCondition((WhereCondition) cond);
2658: } else if (cond instanceof WhereConditionGroup) {
2659: outerWheres.addCondition((WhereConditionGroup) cond);
2660: }
2661: }
2662: }
2663:
2664: /**
2665: * Adds the required condition to <code>outerWheres</code> which tests for the non-existence
2666: * of a property instance value on the search object.
2667: *
2668: * @param profObj
2669: * @param outerWheres
2670: * @param prof
2671: * @param condPropInst
2672: * @throws DataStoreException
2673: * @throws DataAccessException
2674: */
2675: private void addNonExistentPropertyInstanceCondition(
2676: AbstractProfiledObject profObj,
2677: WhereConditionGroup outerWheres, Profile prof,
2678: AbstractPropertyInstance condPropInst)
2679: throws DataStoreException, DataAccessException {
2680: ColumnRef profObjectKeyColRef = m_searchObjectProfile
2681: .getInstanceColumnRef(Profile.ATTRIB_OBJECT_KEY,
2682: profObj.isHistorical());
2683: ColumnRef objObjectKeyColRef = profObj.getInstanceColumnRef(
2684: AbstractObject.ATTRIB_KEY, profObj.isHistorical());
2685:
2686: SelectStatement nestedSelect = new SelectStatement();
2687:
2688: nestedSelect.addSelectColumn(profObjectKeyColRef);
2689:
2690: //prof id column in prop inst table
2691: ColumnRef dataProfIdColref = condPropInst.getInstanceColumnRef(
2692: Profile.TAG_PROFILE, false);
2693:
2694: //prof id column in profile table
2695: ColumnRef profileIdColref = prof.getInstanceColumnRef(
2696: AbstractObject.ATTRIB_ID, prof.isHistorical());
2697:
2698: //join prop inst table to profile table
2699: nestedSelect
2700: .addJoinCondition(dataProfIdColref, profileIdColref);
2701:
2702: //prop id column in prop inst table
2703: ColumnRef dataPropIdColref = condPropInst.getInstanceColumnRef(
2704: Property.TAG_PROPERTY, false);
2705:
2706: nestedSelect.addWhereCondition(dataPropIdColref, "=",
2707: condPropInst.getProperty().getId());
2708:
2709: //only add the following conditions if the property instance
2710: //has values
2711: if (condPropInst.getValues().size() > 0) {
2712: WhereConditionGroup innerWheres = getPropertyInstanceValueConditions(
2713: condPropInst, "=", null);
2714:
2715: if (innerWheres.size() > 1) {
2716: nestedSelect.addWhereCondition(innerWheres);
2717: } else {
2718: //no sense in adding a WhereConditions
2719: //when we can just pick up the only condition
2720: //and add it
2721: Object cond = innerWheres.getCondition(0);
2722: if (cond instanceof WhereCondition) {
2723: nestedSelect
2724: .addWhereCondition((WhereCondition) cond);
2725: } else if (cond instanceof WhereConditionGroup) {
2726: nestedSelect
2727: .addWhereCondition((WhereConditionGroup) cond);
2728: }
2729: }
2730: }
2731:
2732: outerWheres.addCondition(objObjectKeyColRef, "NOT IN",
2733: nestedSelect);
2734: }
2735:
2736: /**
2737: * Sets the logical stringing operator to use between conditions.
2738: *
2739: * @param sOp
2740: */
2741: public void setStringingOperator(String sOp) {
2742: if (sOp.equalsIgnoreCase("and") || sOp.equalsIgnoreCase("or")) {
2743: m_ConditionOperator = sOp;
2744: }
2745:
2746: }
2747:
2748: /**
2749: * Switch caching of results on or off. Default is on.
2750: *
2751: * @param bCache
2752: */
2753: public void cacheResults(boolean bCache) {
2754: m_bCache = bCache;
2755: }
2756:
2757: /**
2758: * Adds core data condition to the given <code>SelectStatement</code>.
2759: *
2760: * @param select
2761: * @throws DataStoreException
2762: */
2763: private void addCoreDataConditions(SelectStatement select)
2764: throws DataStoreException {
2765: for (int i = 0; i < m_ConditionColumns.size(); i++) {
2766: select
2767: .setWhereConditionStringingOperator(m_ConditionOperator);
2768: select
2769: .addWhereCondition((WhereCondition) m_ConditionColumns
2770: .get(i));
2771:
2772: }
2773: }
2774:
2775: /**
2776: * Returns a <code>WhereConditions</code> set of conditions to match on
2777: * the values specified by the given general property instance, using the
2778: * alias given for the property instance table.
2779: *
2780: * @param condPropInst
2781: * @param propInstAlias
2782: * @return @throws
2783: * DataStoreException
2784: * @throws DataAccessException
2785: */
2786: private WhereConditionGroup getPropertyInstanceValueConditions(
2787: GeneralPropertyInstance condPropInst, String sPropOperator,
2788: String propInstAlias) throws DataStoreException,
2789: DataAccessException {
2790:
2791: ColumnRef valColref = condPropInst.getInstanceColumnRef(
2792: AbstractPropertyInstance.TAG_VALUE, false);
2793:
2794: List values = condPropInst.getCalculatedValues();
2795:
2796: if (propInstAlias != null && propInstAlias.length() > 0) {
2797: valColref.setTable(propInstAlias);
2798: }
2799:
2800: // If there are multiple values split into where conditions
2801: // and separate by OR operator. Should be handled by WhereCondition?
2802: WhereConditionGroup valuesWheres = new WhereConditionGroup();
2803:
2804: WhereCondition where = null;
2805:
2806: if (sPropOperator.equals("<>") == true
2807: || sPropOperator.equals("!=")) {
2808: valuesWheres.setStringingOperator("AND");
2809: sPropOperator = "!=";
2810: } else {
2811: valuesWheres.setStringingOperator("OR");
2812: }
2813:
2814: Iterator iter = values.iterator();
2815:
2816: while (iter.hasNext()) {
2817:
2818: where = new WhereCondition(valColref, sPropOperator, iter
2819: .next());
2820:
2821: valuesWheres.addCondition(where);
2822: }
2823:
2824: WhereConditionGroup innerWheres = new WhereConditionGroup();
2825: innerWheres.addCondition(valuesWheres);
2826:
2827: return innerWheres;
2828: }
2829:
2830: /**
2831: * Returns a <code>WhereConditions</code> set of conditions to match on
2832: * the values specified by the given profile property instance, using the
2833: * alias given for the property instance table.
2834: *
2835: * @param condPropInst
2836: * @param propInstAlias
2837: * @return @throws
2838: * DataStoreException
2839: * @throws DataAccessException
2840: */
2841: private WhereConditionGroup getPropertyInstanceValueConditions(
2842: ProfilePropertyInstance condPropInst, String sPropOperator,
2843: String propInstAlias) throws DataStoreException,
2844: DataAccessException {
2845:
2846: List values = condPropInst.getValues();
2847:
2848: // If there are multiple values split into where conditions
2849: // and separate by OR operator. Should be handled by WhereCondition?
2850: WhereConditionGroup valuesWheres = new WhereConditionGroup();
2851: WhereCondition where = null;
2852:
2853: if (sPropOperator.equals("<>") == true
2854: || sPropOperator.equals("!=")) {
2855: valuesWheres.setStringingOperator("AND");
2856: sPropOperator = "!=";
2857: } else {
2858: valuesWheres.setStringingOperator("OR");
2859: }
2860:
2861: Iterator iter = values.iterator();
2862:
2863: while (iter.hasNext()) {
2864: Profile prof = (Profile) iter.next();
2865:
2866: String sName = prof.getName();
2867:
2868: ColumnRef nameCol = prof.getInstanceColumnRef(
2869: AbstractObject.ATTRIB_NAME, false);
2870:
2871: if (propInstAlias != null && propInstAlias.length() > 0) {
2872: nameCol.setTable(propInstAlias);
2873: }
2874:
2875: where = new WhereCondition(nameCol, sPropOperator, sName);
2876:
2877: valuesWheres.addCondition(where);
2878: }
2879:
2880: WhereConditionGroup innerWheres = new WhereConditionGroup();
2881: innerWheres.addCondition(valuesWheres);
2882:
2883: return innerWheres;
2884:
2885: }
2886:
2887: /**
2888: * Returns a <code>WhereConditions</code> set of conditions to match on
2889: * the values specified by the given child object property instance, using
2890: * the alias given for the property instance table.
2891: *
2892: * @param condPropInst
2893: * @param propInstAlias
2894: * @return @throws
2895: * DataStoreException
2896: * @throws DataAccessException
2897: */
2898: private WhereConditionGroup getPropertyInstanceValueConditions(
2899: ChildObjectPropertyInstance condPropInst,
2900: String sPropOperator, String propInstAlias)
2901: throws DataStoreException, DataAccessException {
2902:
2903: ColumnRef valColref = condPropInst.getInstanceColumnRef(
2904: AbstractPropertyInstance.TAG_VALUE, false);
2905:
2906: List values = condPropInst.getValues();
2907:
2908: if (propInstAlias != null && propInstAlias.length() > 0) {
2909: valColref.setTable(propInstAlias);
2910: }
2911:
2912: // If there are multiple values split into where conditions
2913: // and separate by OR operator. Should be handled by WhereCondition?
2914: WhereConditionGroup valuesWheres = new WhereConditionGroup();
2915: WhereCondition where = null;
2916:
2917: AbstractChildObject child = null;
2918:
2919: if (sPropOperator.equals("<>") == true) {
2920: valuesWheres.setStringingOperator("AND");
2921: sPropOperator = "!=";
2922: } else {
2923: valuesWheres.setStringingOperator("OR");
2924: }
2925:
2926: for (Iterator iter = values.iterator(); iter.hasNext();) {
2927: child = (AbstractChildObject) iter.next();
2928: int nChildId = child.getId();
2929:
2930: if (nChildId > 0) {
2931: //condition is based on object id
2932: where = new WhereCondition(valColref, sPropOperator,
2933: nChildId);
2934: } else {
2935: //assume that we're doing a search on name
2936:
2937: String sName = child.getName();
2938:
2939: if (sName != null) {
2940: ColumnRef objIdCol = child.getInstanceColumnRef(
2941: AbstractObject.ATTRIB_ID, child
2942: .isHistorical());
2943: ColumnRef objNameCol = child.getInstanceColumnRef(
2944: AbstractObject.TAG_NAME, child
2945: .isHistorical());
2946:
2947: String objAlias = condPropInst.getName() + "_"
2948: + child.getDBTableName();
2949:
2950: objIdCol.setTableAlias(objAlias);
2951: objNameCol.setTableAlias(objAlias);
2952:
2953: //condition is based on object id
2954: where = new WhereCondition(objNameCol, condPropInst
2955: .getOperator(), sName);
2956:
2957: JoinConditions join = new JoinConditions();
2958:
2959: join.addCondition(objIdCol, valColref);
2960:
2961: where.addAssociatedJoinConditions(join);
2962: }
2963: }
2964:
2965: valuesWheres.addCondition(where);
2966: }
2967:
2968: WhereConditionGroup innerWheres = new WhereConditionGroup();
2969: innerWheres.addCondition(valuesWheres);
2970:
2971: return innerWheres;
2972:
2973: }
2974:
2975: /**
2976: * Returns a <code>WhereConditions</code> set of conditions to match on
2977: * the values specified by the given property instance, using the alias
2978: * given for the property instance table.
2979: *
2980: * @param condPropInst
2981: * @param condOperator TODO
2982: * @param propInstAlias
2983: * @return
2984: * @throws DataStoreException
2985: * @throws DataAccessException
2986: */
2987: private WhereConditionGroup getPropertyInstanceValueConditions(
2988: AbstractPropertyInstance condPropInst, String condOperator,
2989: String propInstAlias) throws DataStoreException,
2990: DataAccessException {
2991: WhereConditionGroup innerWheres = null;
2992:
2993: if (condPropInst instanceof GeneralPropertyInstance) {
2994: innerWheres = getPropertyInstanceValueConditions(
2995: (GeneralPropertyInstance) condPropInst,
2996: condOperator, propInstAlias);
2997: } else if (condPropInst instanceof ProfilePropertyInstance) {
2998: innerWheres = getPropertyInstanceValueConditions(
2999: (ProfilePropertyInstance) condPropInst,
3000: condOperator, propInstAlias);
3001: } else if (condPropInst instanceof ChildObjectPropertyInstance) {
3002: innerWheres = getPropertyInstanceValueConditions(
3003: (ChildObjectPropertyInstance) condPropInst,
3004: condOperator, propInstAlias);
3005: }
3006:
3007: return innerWheres;
3008: }
3009:
3010: /**
3011: * @return
3012: */
3013: public boolean isApprovedSearch() {
3014: return m_bApprovedSearch;
3015: }
3016:
3017: /**
3018: * @param b
3019: */
3020: public void setApproved(boolean bApproved) {
3021: m_bApprovedSearch = bApproved;
3022: }
3023:
3024: /**
3025: * @return
3026: */
3027: public List getConditionProfile() {
3028: return m_ConditionProfile;
3029: }
3030:
3031: /**
3032: * @return Returns the m_ConditionGroups.
3033: */
3034: public List getConditionGroups() {
3035: return m_ConditionGroups;
3036: }
3037:
3038: /**
3039: * @return Returns the m_SearchColumns.
3040: */
3041: public List getSearchColumns() {
3042: return m_SearchColumns;
3043: }
3044: }
|