示例#1
0
    def query_struct(self):
        self.fetch_token()
        if (self.currentToken == '@attr'):
            attrs = []
            while self.currentToken == '@attr':
                attrs.append(self.attr_spec())
                self.fetch_token()
            t = self.term()

            # Now we have attrs + term
            clause = z3950.AttributesPlusTerm()
            clause.attributes = [make_attr(*e) for e in attrs]
            clause.term = t
            return ('op', ('attrTerm', clause))
        elif (self.is_boolean()):
            # @operator query query
            return self.complex()
        elif (self.currentToken == '@set'):
            return self.result_set()
        elif (self.currentToken == "{"):
            # Parens
            s = self.query_struct()
            if (self.nextToken <> "}"):
                raise (ValueError)
            else:
                self.fetch_token()
            return s

        else:
            t = self.term()
            return self.defaultClause(t)
示例#2
0
def tree_to_q (ast):
    if ast.type == 'op':
        myrpnRpnOp = z3950.RpnRpnOp ()
        myrpnRpnOp.rpn1 = tree_to_q(ast.children[0])
        myrpnRpnOp.rpn2 = tree_to_q(ast.children[1])
        op = ast.leaf.lower ()
        if op == 'not': op = 'and-not' # CCL spec of 'not' vs. Z39.50 spec of 'and-not'
        myrpnRpnOp.op = (op, None)
        return ('rpnRpnOp', myrpnRpnOp)
    elif ast.type == 'relop':
        # XXX but e.g. LC (http://lcweb.loc.gov/z3950/lcserver.html)
        # doesn't support other relation attributes, either.
        try:
            relattr = relop_to_attrib [ast.leaf]
        except(KeyError):  # should never happen, how could we have lexed it?
            raise UnimplError (ast.leaf)
        def make_aelt (qual):
            val = ('numeric', qual [1])
            return z3950.AttributeElement (attributeType = qual[0],
                                           attributeValue = val)
        apt  = z3950.AttributesPlusTerm ()
        quallist = ast.children.quallist
        if ast.leaf != '=':
            quallist.append ((2,relattr)) # 2 is relation attribute
            # see http://www.loc.gov/z3950/agency/markup/13.html ATR.1.1
        apt.attributes = map (make_aelt, quallist)
        apt.term = ('general', ast.children.val) # XXX update for V3?
        return ('op', ('attrTerm', apt))
    elif ast.type == 'set':
        return ('op', ('resultSet', ast.leaf))
        
    raise UnimplError("Bad ast type " + str(ast.type))
示例#3
0
 def defaultClause(self, t):
     # Assign a default clause: anywhere =
     clause = z3950.AttributesPlusTerm()
     attrs = [(oids.Z3950_ATTRS_BIB1, 1, 1016), (oids.Z3950_ATTRS_BIB1, 2, 3)]
     clause.attributes = [make_attr(*e) for e in attrs]
     clause.term = t
     return ('op', ('attrTerm', clause))
示例#4
0
    def toRPN(self, top=None):
        if not top:
            top = self

        if (self.relation.value in ['any', 'all']):
            # Need to split this into and/or tree
            if (self.relation.value == 'any'):
                bool = " or "
            else:
                bool = " and "
            words = self.term.value.split()
            self.relation.value = '='
            # Add 'word' relationModifier
            self.relation.modifiers.append(CModifierClause('cql.word'))

            # Create CQL, parse it, walk new tree
            idxrel = "%s %s" % (self.index.toCQL(), self.relation.toCQL())
            text = []
            for w in words:
                text.append('%s "%s"' % (idxrel, w))
            cql = bool.join(text)
            tree = parse(cql)
            tree.prefixes = self.prefixes
            tree.parent = self.parent
            tree.config = self.config
            return tree.toRPN(top)
        else:
            # attributes, term
            # AttributeElement: attributeType, attributeValue
            # attributeValue ('numeric', n) or ('complex', struct)
            if (self.index.value == 'resultsetid'):
                return ('op', ('resultSet', self.term.value))

            clause = z3950.AttributesPlusTerm()
            attrs = self.index.toRPN(top)
            if (self.term.value.isdigit()):
                self.relation.modifiers.append(CModifierClause('cql.number'))
            relattrs = self.relation.toRPN(top)
            attrs.update(relattrs)
            butes = []
            for e in attrs.iteritems():
                butes.append((e[0][0], e[0][1], e[1]))

            clause.attributes = [make_attr(*e) for e in butes]
            clause.term = self.term.toRPN(top)

            return ('op', ('attrTerm', clause))
示例#5
0
    def clause(self):

        if (self.is_boolean(self.nextToken) or not self.nextToken
                or self.nextToken.lower() == 'resultsetid'
                or self.nextToken == ")"):
            # Must be a resultset
            tok = self.currentToken
            self.fetch_token()
            return ('op', ('resultSet', tok))

        elif (self.currentToken == '['):
            # List of attributes
            attrs = []
            oidHash = oids.oids['Z3950']['ATTRS']
            while (1):
                self.fetch_token()

                if (self.currentToken == ']'):
                    break

                if (self.currentToken in oidHash):
                    attrSet = oidHash[self.currentToken]['ov']
                    self.fetch_token()
                elif (self.currentToken[:8] == '1.2.840.'):
                    attrSet = asn1.OidVal(
                        list(map(int, self.currentToken.split('.'))))
                    self.fetch_token()
                else:
                    attrSet = None

                if (self.currentToken[-1] == ','):
                    tok = self.currentToken[:-1]
                else:
                    tok = self.currentToken

                if (tok.isdigit()):
                    # 1 = foo
                    atype = int(tok)
                    self.fetch_token()
                    if (self.currentToken == '='):
                        # = foo
                        self.fetch_token()

                    if (self.currentToken[0] == '='):
                        # =foo
                        tok = self.currentToken[1:]
                    else:
                        tok = self.currentToken

                    if (tok[-1] == ','):
                        tok = tok[:-1]

                    if (tok.isdigit()):
                        val = int(tok)
                    else:
                        val = tok
                        if (val[0] == "'" and val[-1] == "'"):
                            val = val[1:-1]
                elif (tok[-1] == '='):
                    #1= foo
                    tok = tok[:-1]
                    if (tok.isdigit()):
                        atype = int(tok)
                    self.fetch_token()
                    if (self.currentToken[-1] == ","):
                        tok = self.currentToken[:-1]
                    else:
                        tok = self.currentToken
                    if (tok.isdigit()):
                        val = int(self.currentToken)
                    else:
                        val = tok
                        if (val[0] == "'" and val[-1] == "'"):
                            val = val[1:-1]

                elif (tok.find('=') > -1):
                    # 1=foo
                    (atype, val) = self.currentToken.split('=')
                    atype = int(atype)
                    if (val[-1] == ","):
                        val = val[:-1]
                    if (val.isdigit()):
                        val = int(val)
                    elif (val[0] == "'" and val[-1] == "'"):
                        val = val[1:-1]
                else:
                    # ???
                    raise ValueError
                attrs.append([attrSet, atype, val])

        else:
            # Check for named index
            if (self.currentToken.lower() in zconfig.bib1):
                attrs = [[
                    oids.Z3950_ATTRS_BIB1_ov, 1,
                    zconfig.bib1[self.currentToken.lower()]
                ]]
            else:
                # Just pass through the name
                attrs = [[oids.Z3950_ATTRS_BIB1_ov, 1, self.currentToken]]

        self.fetch_token()
        # Check for relation
        tok = self.currentToken.upper()
        if (tok in relations):
            val = relations[tok]
            found = 0
            for a in attrs:
                if (a[0] in [oids.Z3950_ATTRS_BIB1, None] and a[1] == 2):
                    found = 1
                    a[2] = val
                    break
            if (not found):
                attrs.append([None, 2, val])
            self.fetch_token()
        elif (tok in geoRelations):
            val = geoRelations[tok]
            found = 0
            for a in attrs:
                if (a[0]
                        in [oids.Z3950_ATTRS_BIB1, oids.Z3950_ATTRS_GEO, None]
                        and a[1] == 2):
                    found = 1
                    a[2] = val
                    break
            if (not found):
                attrs.append([oids.Z3950_ATTRS_GEO, 2, val])
            self.fetch_token()

        if (self.currentToken.find(' ')):
            # Already quoted
            term = self.currentToken
        else:
            # Accumulate
            term = []
            while (self.currentToken and not self.is_boolean(self.currentToken)
                   and self.currentToken.lower() != 'resultsetid'):
                term.append(self.currenToken)
            term = ' '.join(term)

        self.fetch_token()

        # Phew. Now build AttributesPlusTerm
        clause = z3950.AttributesPlusTerm()
        clause.attributes = [make_attr(*e) for e in attrs]
        clause.term = ('general', term)
        return ('op', ('attrTerm', clause))