############################################################################### ## ## ## ALEXANDRIA DIGITAL LIBRARY ## ## University of California at Santa Barbara ## ## ## ## ------------------------------------------------------------------------- ## ## ## ## Copyright (c) 2003 by the Regents of the University of California ## ## All rights reserved ## ## ## ## Redistribution and use in source and binary forms, with or without ## ## modification, are permitted provided that the following conditions are ## ## met: ## ## ## ## 1. Redistributions of source code must retain the above copyright ## ## notice, this list of conditions, and the following disclaimer. ## ## ## ## 2. Redistributions in binary form must reproduce the above copyright ## ## notice, this list of conditions, and the following disclaimer in ## ## the documentation and/or other materials provided with the ## ## distribution. ## ## ## ## 3. All advertising materials mentioning features or use of this ## ## software must display the following acknowledgement: This product ## ## includes software developed by the Alexandria Digital Library, ## ## University of California at Santa Barbara, and its contributors. ## ## ## ## 4. Neither the name of the University nor the names of its ## ## contributors may be used to endorse or promote products derived ## ## from this software without specific prior written permission. ## ## ## ## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY ## ## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ## ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE ## ## DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ## ## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ## ## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ## ## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ## ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ## ## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ## ## ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ## ## POSSIBILITY OF SUCH DAMAGE. ## ## ## ############################################################################### # $Header: /export/home/gjanee/bucket99/paradigms/RCS/Adaptor_IndirectQualification.py,v 1.2 2003/10/28 21:53:08 gjanee Exp $ # SYNOPSIS # # Adaptor_IndirectQualification (mainFieldColumn, auxiliaryTable, # auxiliaryFieldColumn, auxiliaryUriColumn, paradigm) # # mainFieldColumn # The main table column that contains field keys, e.g., # "field_code". # # auxiliaryTable # The auxiliary table that stores field information, e.g., # "fields". # # auxiliaryFieldColumn # The auxiliary table column to be joined with # 'mainFieldColumn', e.g., "field_code". # # auxiliaryUriColumn # The auxiliary table column that stores field URIs, e.g., # "field_uri". # # paradigm # The underlying paradigm. # # DESCRIPTION # # An adaptor that adds support for field-level searching to a # paradigm (the "underlying" paradigm) by adding a condition to # each SELECT statement returned by the paradigm. # # The underlying paradigm must return, given an appropriate atomic # bucket-level constraint, a Select object that queries exactly # one main table, i.e., a SELECT statement of the form: # # SELECT idColumn FROM mainTable, ... # WHERE condition # # This adaptor passes constraints through to the underlying # paradigm; the paradigm should treat all constraints as being # bucket-level. The translations of bucket-level constraints are # returned unmodified. But given a field-level constraint, this # adaptor adds an INNER JOIN to an auxiliary table and adds a # condition to the SELECT statement's WHERE clause: # # SELECT idColumn FROM mainTable, ..., auxiliaryTable # WHERE mainTable.mainFieldColumn = # auxiliaryTable.auxiliaryFieldColumn AND # auxiliaryUriColumn = 'F.uri' AND # condition # # where F.uri is the URI of the field mentioned in the constraint. # # Thus this adaptor is useful in situations in which a table # stores multiple values (in multiple rows) per collection item # and the values are directly qualified by a field code which # serves as a foreign key into a table of field URIs. The # underlying paradigm should generally indicate that the # cardinality of the main table is isMany(). # # Exceptions thrown: # # none # # AUTHOR # # Greg Janee # gjanee@alexandria.ucsb.edu # # HISTORY # # $Log: Adaptor_IndirectQualification.py,v $ # Revision 1.2 2003/10/28 21:53:08 gjanee # Per revision 1.8 of UniversalTranslator.py, this paradigm now # invokes field-level methods of the underlying paradigm if the # latter supports field-level searching. # # Revision 1.1 2002/10/17 00:38:59 gjanee # Initial revision # import types import edu.ucsb.adl.middleware M = edu.ucsb.adl.middleware import UniversalTranslator UT = UniversalTranslator class Adaptor_IndirectQualification (UT.FieldSearchableParadigm): def __init__ (self, mainFieldColumn, auxiliaryTable, auxiliaryFieldColumn, auxiliaryUriColumn, paradigm): UT.assertType(mainFieldColumn, types.StringType) UT.assertType(auxiliaryTable, types.StringType) UT.assertType(auxiliaryFieldColumn, types.StringType) UT.assertType(auxiliaryUriColumn, types.StringType) UT.assertType(paradigm, UT.Paradigm) self.mainFieldColumn = mainFieldColumn self.auxiliaryTable = auxiliaryTable self.auxiliaryFieldColumn = auxiliaryFieldColumn self.auxiliaryUriColumn = auxiliaryUriColumn self.paradigm = paradigm def translateBucketAtomic (self, constraint, vocabularies): return self.paradigm.translateBucketAtomic(constraint, vocabularies) def translateBucketBoolean (self, operator, constraints, vocabularies): return self.paradigm.translateBucketBoolean(operator, constraints, vocabularies) def translateFieldAtomic (self, constraint, vocabularies): UT.assertType(constraint, M.Query.SimpleConstraint) assert constraint.getField() != None, "no field constraint" if isinstance(self.paradigm, UT.FieldSearchableParadigm): query = self.paradigm.translateFieldAtomic(constraint, vocabularies) else: query = self.paradigm.translateBucketAtomic(constraint, vocabularies) return self._process(query, constraint.getField().uri) def translateFieldBoolean (self, operator, constraints, vocabularies): UT.assertBooleanOperator(operator) UT.assertType(constraints, types.ListType) UT.assertListElementType(constraints, M.Query.SimpleConstraint) UT.assertBooleanOperatorOperandConsistency(operator, constraints) UT.assertListElementCommonValue(constraints, lambda c: c.getBucket()) UT.assertListElementPredicateAll(constraints, lambda c: c.getField() != None) UT.assertListElementCommonValue(constraints, lambda c: c.getField().uri) if isinstance(self.paradigm, UT.FieldSearchableParadigm): query = self.paradigm.translateFieldBoolean(operator, constraints, vocabularies) else: query = self.paradigm.translateBucketBoolean(operator, constraints, vocabularies) if query == None or isinstance(query, UT.Query): return None else: return self._process(query, constraints[0].getField().uri) def _process (self, query, uri): UT.assertType(query, UT.Select) UT.assertType(uri, types.StringType) mainTable = None for f in query.froms: if isinstance(f, UT.MainFrom): assert mainTable == None, "underlying paradigm returned " +\ "multiple main table references" mainTable = f.table table = UT.TableRef(self.auxiliaryTable) auxiliaryExpression = UT.Expression([table, "." +\ self.auxiliaryUriColumn + " = '" + UT.protectQuotes(uri) + "'"]) return UT.Select(query.froms +\ [UT.AuxiliaryFrom(table, UT.Expression([table, "." + self.auxiliaryFieldColumn + " = ", mainTable, "." + self.mainFieldColumn]))], auxiliaryExpression.combine("AND", query.expression))