htsql-firebird / src / htsql / core / model.py

#
# Copyright (c) 2006-2012, Prometheus Research, LLC
# See `LICENSE` for license information, `AUTHORS` for the list of authors.
#


from .util import Comparable, Printable, Clonable, maybe, listof, tupleof
from .domain import Domain
from .entity import TableEntity, ColumnEntity, Join
from .tr.syntax import Syntax


class Model(Comparable, Clonable, Printable):
    pass


class Node(Model):
    pass


class Arc(Model):

    def __init__(self, origin, target, arity, is_expanding, is_contracting,
                 equality_vector):
        assert isinstance(origin, Node)
        assert isinstance(target, Node)
        assert isinstance(arity, maybe(int))
        assert isinstance(is_expanding, bool)
        assert isinstance(is_contracting, bool)
        super(Arc, self).__init__(equality_vector)
        self.origin = origin
        self.target = target
        self.arity = arity
        self.is_expanding = is_expanding
        self.is_contracting = is_contracting

    def reverse(self):
        return None


class Label(Clonable, Printable):

    def __init__(self, name, arc, is_public):
        assert isinstance(name, unicode)
        assert isinstance(arc, Arc)
        assert isinstance(is_public, bool)
        assert arc.arity is None or not is_public
        self.name = name
        self.arc = arc
        self.origin = arc.origin
        self.target = arc.target
        self.arity = arc.arity
        self.is_expanding = arc.is_expanding
        self.is_contracting = arc.is_contracting
        self.is_public = is_public

    def __str__(self):
        return "%s%s (%s): %s -> %s" % (self.name.encode('utf-8'),
                                        "(%s)" % ",".join(["_"]*self.arity)
                                        if self.arity is not None else "",
                                        self.arc, self.origin, self.target)


class HomeNode(Node):

    def __init__(self):
        super(HomeNode, self).__init__(equality_vector=())

    def __str__(self):
        return "()"


class TableNode(Node):

    def __init__(self, table):
        assert isinstance(table, TableEntity)
        super(TableNode, self).__init__(equality_vector=(table,))
        self.table = table

    def __str__(self):
        return str(self.table)


class DomainNode(Node):

    def __init__(self, domain):
        assert isinstance(domain, Domain)
        super(DomainNode, self).__init__(equality_vector=(domain,))
        self.domain = domain

    def __str__(self):
        return str(self.domain)


class UnknownNode(Node):

    def __init__(self):
        super(UnknownNode, self).__init__(equality_vector=())

    def __str__(self):
        return "?"


class InvalidNode(Node):

    def __init__(self):
        super(InvalidNode, self).__init__(equality_vector=())

    def __str__(self):
        return "!"


class TableArc(Arc):

    def __init__(self, table):
        assert isinstance(table, TableEntity)
        super(TableArc, self).__init__(
                origin=HomeNode(),
                target=TableNode(table),
                arity=None,
                is_expanding=False,
                is_contracting=False,
                equality_vector=(table,))
        self.table = table

    def __str__(self):
        return str(self.table)


class ChainArc(Arc):

    def __init__(self, table, joins):
        assert isinstance(table, TableEntity)
        assert isinstance(joins, listof(Join)) and len(joins) > 0
        assert table == joins[0].origin
        super(ChainArc, self).__init__(
                origin=TableNode(joins[0].origin),
                target=TableNode(joins[-1].target),
                arity=None,
                is_expanding=all(join.is_expanding for join in joins),
                is_contracting=all(join.is_contracting for join in joins),
                equality_vector=(table, tuple(joins),))
        self.table = table
        self.joins = joins
        self.is_direct = all(join.is_direct for join in joins)
        self.is_reverse = all(join.is_reverse for join in joins)

    def reverse(self):
        return ChainArc(self.target.table,
                        [join.reverse() for join in reversed(self.joins)])

    def __str__(self):
        return " => ".join("(%s)" % join for join in self.joins)


class ColumnArc(Arc):

    def __init__(self, table, column, link=None):
        assert isinstance(table, TableEntity)
        assert isinstance(column, ColumnEntity) and column.table is table
        assert isinstance(link, maybe(Arc))
        if link is not None:
            assert link.origin == TableNode(table)
        super(ColumnArc, self).__init__(
                origin=TableNode(table),
                target=DomainNode(column.domain),
                arity=None,
                is_expanding=(not column.is_nullable),
                is_contracting=True,
                equality_vector=(table, column))
        self.table = table
        self.column = column
        self.link = link

    def __str__(self):
        return str(self.column)


class SyntaxArc(Arc):

    def __init__(self, origin, parameters, syntax):
        assert isinstance(parameters, maybe(listof(tupleof(unicode, bool))))
        assert isinstance(syntax, Syntax)
        super(SyntaxArc, self).__init__(
                origin=origin,
                target=UnknownNode(),
                arity=(len(parameters) if parameters is not None else None),
                is_expanding=False,
                is_contracting=False,
                equality_vector=(origin, tuple(parameters)
                                         if parameters is not None else None,
                                 syntax))
        self.parameters = parameters
        self.syntax = syntax

    def __str__(self):
        return str(self.syntax)


class InvalidArc(Arc):

    def __init__(self, origin, arity, equality_vector):
        assert isinstance(origin, Node)
        super(InvalidArc, self).__init__(
                origin=origin,
                target=InvalidNode(),
                arity=arity,
                is_expanding=False,
                is_contracting=False,
                equality_vector=equality_vector)

    def __str__(self):
        return "!"


class AmbiguousArc(InvalidArc):

    def __init__(self, arity, alternatives):
        assert isinstance(alternatives, listof(Arc)) and len(alternatives) > 0
        origin = alternatives[0].origin
        assert all(alternative.origin == origin
                   for alternative in alternatives)
        super(AmbiguousArc, self).__init__(
                origin=origin,
                arity=arity,
                equality_vector=(origin, tuple(alternatives)))
        self.alternatives = alternatives

    def __str__(self):
        return "?(%s)" % ", ".join(str(alternative)
                                   for alternative in self.alternatives)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.