Beispiel #1
0
 def __init__(self, database, logLevel='INFO'):
     self.db = database
     self.logger = Logger(__name__, level=logLevel)
     super(BaseListener, self).__init__()
     self.session = database.session
     self.bakery = baked.bakery()
     self.bake_common_queries()
Beispiel #2
0
 def __init__(self, database, logLevel = 'INFO', *args, **kws):
     super(LdfListener, self).__init__(database, logLevel, *args, **kws)
     self.logger = Logger(__name__, level = logLevel)
     self.nodes = {}
     self.signals = {}
     self.frames = {}
     self.event_trigged_frames = []
     self.bake_queries()
     self.insertNetwork()
Beispiel #3
0
class Creator(object):

    def __init__(self, db):
        self.db = db
        self.logger = Logger(__name__)

    def drop(self, entity, items):
        cur = self.db.getCursor()
        for item in items:
            self.logger.debug("Dropping {} '{}'.".format(entity.lower(), item))
            try:
                cur.execute("DROP {} IF EXISTS {}".format(entity.upper(), item))
            except sqlite3.DatabaseError as e:
                self.logger.error("Deletion of {} '{}' failed : '{}'".format(entity.lower(), item, str(e)))
                raise

    def dropTables(self):
        cur = self.db.getCursor()
        self.db.beginTransaction()
        self.drop("table", TABLES)
        self.drop("view", VIEWS)
        self.db.commitTransaction()

    def createSchema(self):
        cur = self.db.getCursor()
        self.executeItems(SCHEMA, "table")
        self.executeItems(TRIGGER, "trigger")
        self.insertDefaults(cur)

    def insertDefaults(self, cur):
        self.executeItems(DEFAULTS, "default")

    def createIndices(self):
        self.executeItems(INDICES, "index")

    def createMetaData(self):
        sql = "INSERT OR REPLACE INTO VndbMeta(RID, Schema_Version) VALUES(1, {})".format(VNDB_SCHEMA_VERSION)
        self.executeItem(sql, "meta-data", transactional = True)

    def executeItem(self, item, name, cur = None, transactional = False):
        if not cur:
            cur = self.db.getCursor()
        if transactional:
            self.db.beginTransaction()
        self.logger.debug("Creating {} '{}'.".format(name, item))
        try:
            res = cur.execute(item)
        except sqlite3.DatabaseError as e:
            self.logger.error("Creation of {} '{}' failed : '{}'".format(name, item, str(e)))
            #raise
        if transactional:
            self.db.commitTransaction()

    def executeItems(self, items, name):
        cur = self.db.getCursor()
        self.db.beginTransaction()
        for item in items:
            self.executeItem(item, name, cur)
        self.db.commitTransaction()
Beispiel #4
0
class BaseListener(antlr4.ParseTreeListener):
    """
    """

    value = []
    logger = Logger(__name__)

    def getList(self, attr):
        return [x for x in attr()] if attr() else []

    def getTerminal(self, attr):
        return attr().getText() if attr() else ''

    def exitIntValue(self, ctx):
        if ctx.i:
            ctx.value = int(ctx.i.text, 10)
        elif ctx.h:
            ctx.value = int(ctx.h.text, 16)
        else:
            ctx.value = None

    def exitFloatValue(self, ctx):
        ctx.value = float(ctx.f.text) if ctx.f else None

    def exitNumber(self, ctx):
        if ctx.i:
            value = ctx.i.value
        elif ctx.f:
            value = ctx.f.value
        else:
            value = None
        ctx.value = value

    def exitStringValue(self, ctx):
        ctx.value = ctx.s.text.strip('"') if ctx.s else None

    def exitIdentifierValue(self, ctx):
        ctx.value = ctx.i.text if ctx.i else None

    def _formatMessage(self, msg, location):
        return "[{0}:{1}] {2}".format(location.start.line,
                                      location.start.column + 1, msg)

    def _log(self, method, msg, location=None):
        if location:
            method(self._formatMessage(msg, location))
        else:
            method(msg)

    def info(self, msg, location=None):
        self._log(self.info.warn, msg, location)

    def warn(self, msg, location=None):
        self._log(self.logger.warn, msg, location)

    def error(self, msg, location=None):
        self._log(self.logger.warn, msg, location)

    def debug(self, msg, location=None):
        self._log(self.logger.warn, msg, location)
Beispiel #5
0
 def __init__(self,
              filename=":memory:",
              debug=False,
              logLevel='INFO',
              create=True):
     if filename == ':memory:':
         self.dbname = ""
     else:
         if not filename.lower().endswith(DB_EXTENSION):
             self.dbname = "{}.{}".format(filename, DB_EXTENSION)
         else:
             self.dbname = filename
     self._engine = create_engine("sqlite:///{}".format(self.dbname),
                                  echo=debug,
                                  connect_args={
                                      'detect_types':
                                      sqlite3.PARSE_DECLTYPES
                                      | sqlite3.PARSE_COLNAMES
                                  },
                                  native_datetime=True)
     self._session = orm.Session(self._engine,
                                 autoflush=False,
                                 autocommit=False)
     self._metadata = model.Base.metadata
     if create == True:
         model.Base.metadata.create_all(self.engine)
         self.session.flush()
         self.session.commit()
     self.logger = Logger(__name__, level=logLevel)
Beispiel #6
0
 def __init__(self, filename = ":memory:", inMemory = False, cachesize = 4, logLevel = 'INFO'):
     self._name,_ = os.path.splitext(filename)
     if inMemory:
         self._dbname = ":memory:"
     else:
         if not filename.lower().endswith(DB_EXTENSION):
             self._dbname = "{}.{}".format(filename, DB_EXTENSION)
         else:
             self._dbname = filename
     self._filename = filename
     self.conn = sqlite3.connect(self.dbname, isolation_level = None)
     self.conn.create_function("REGEXP", 2, regexer)
     self.conn.isolation_level = None
     self.cachesize = cachesize
     self.setPragmas()
     self._filename = filename
     self.logger = Logger('db', level = logLevel)
Beispiel #7
0
    def __init__(self, name, encoding="latin-1", debug=False):
        self.logger = Logger(__name__)
        self.encoding = encoding
        self.fname = name.parts[-1]
        self.fnbase = name.stem
        self.fnext = name.suffix[1:].lower()
        self.fabsolute = name.absolute()

        self.db = VNDB(r"{}.vndb".format(self.fnbase), debug=debug)
Beispiel #8
0
    def __init__(self,
                 dbname,
                 dbtype="CAN",
                 template=None,
                 inMemory=False,
                 logLevel='INFO'):
        """
        """
        self.logger = Logger("api.database", level=logLevel)
        self.logger.debug("Initializing Sqlite3 database '{}'".format(dbname))
        self.dbtype = dbtype  # TODO: check.
        self.db = CanDatabase(dbname, logLevel=logLevel, inMemory=inMemory)
        creator = Creator(self.db)

        self.queries = Queries(self.db)

        creator.createSchema()
        creator.createIndices()

        self.db.beginTransaction()
Beispiel #9
0
 def __init__(self, db, queryClass):
     self.db = db
     self.queries = queryClass(db)
     self.logger = Logger(__name__)
Beispiel #10
0
class BaseListener(antlr4.ParseTreeListener):
    """
    """

    value = []

    def __init__(self, database, logLevel='INFO'):
        self.db = database
        self.logger = Logger(__name__, level=logLevel)
        super(BaseListener, self).__init__()
        self.session = database.session
        self.bakery = baked.bakery()
        self.bake_common_queries()

    def bake_common_queries(self):
        self.ATTRIBUTE_DEFINITION_BY_NAME = self.bakery(lambda session: self.session.query(Attribute_Definition).\
            filter(Attribute_Definition.name == bindparam('name')))
        self.MESSAGE_BY_NAME = self.bakery(lambda session: session.query(
            Message).filter(Message.name == bindparam('name')))
        self.NODE_BY_NAME = self.bakery(lambda session: session.query(Node).
                                        filter(Node.name == bindparam('name')))
        self.NODE_BY_RID = self.bakery(lambda session: session.query(Node).
                                       filter(Node.rid == bindparam('rid')))
        self.SIGNAL_BY_NAME = self.bakery(lambda session: session.query(
            Signal).filter(Signal.name == bindparam('name')))
        self.SIGNAL_BY_RID = self.bakery(lambda session: session.query(
            Signal).filter(Signal.rid == bindparam('rid')))

    def log_insertion(self, table_name):
        self.logger.debug("Inserting values for '{}'.".format(table_name))

    def getList(self, attr):
        return [x for x in attr] if attr else []

    def getTerminal(self, attr, default=None):
        return attr.text if attr else default

    def getValue(self, attr, default=None):
        return attr.value if attr else default

    def exitIntValue(self, ctx):
        if ctx.i:
            ctx.value = toInt(ctx.i.text, 10)
        elif ctx.h:
            ctx.value = toInt(ctx.h.text, 16)
        else:
            ctx.value = None

    def exitFloatValue(self, ctx):
        ctx.value = toFloat(ctx.f.text) if ctx.f else None

    def exitNumber(self, ctx):
        if ctx.i:
            value = ctx.i.value
        elif ctx.f:
            value = ctx.f.value
        else:
            value = None
        ctx.value = value

    def exitStringValue(self, ctx):
        value = ctx.s.text.strip('"') if ctx.s else None
        ctx.value = value

    def exitIdentifierValue(self, ctx):
        value = ctx.i.text if ctx.i else None
        value = None if value == "<missing C_IDENTIFIER>" else value
        ctx.value = value

    def _formatMessage(self, msg, location):
        return "[{0}:{1}] {2}".format(location.start.line,
                                      location.start.column + 1, msg)

    def _log(self, method, msg, location=None):
        if location:
            method(self._formatMessage(msg, location))
        else:
            method(msg)

    def info(self, msg, location=None):
        self._log(self.info.warn, msg, location)

    def warn(self, msg, location=None):
        self._log(self.logger.warn, msg, location)

    def error(self, msg, location=None):
        self._log(self.logger.warn, msg, location)

    def debug(self, msg, location=None):
        self._log(self.logger.warn, msg, location)
Beispiel #11
0
class Database:
    """
    """

    DBC_TEMPLATE = pkgutil.get_data("pydbc", "cgen/templates/dbc.tmpl")

    def __init__(self,
                 dbname,
                 dbtype="CAN",
                 template=None,
                 inMemory=False,
                 logLevel='INFO'):
        """
        """
        self.logger = Logger("api.database", level=logLevel)
        self.logger.debug("Initializing Sqlite3 database '{}'".format(dbname))
        self.dbtype = dbtype  # TODO: check.
        self.db = CanDatabase(dbname, logLevel=logLevel, inMemory=inMemory)
        creator = Creator(self.db)

        self.queries = Queries(self.db)

        creator.createSchema()
        creator.createIndices()

        self.db.beginTransaction()

    def __str__(self):
        return "{}(name: {})".format(self.__class__.__name__, self.dbname)

    def __del__(self):
        self.close()

    @property
    def dbname(self):
        return self.db.dbname

    def name(self):
        return self.db.name

    def close(self):
        self.db.close()

    def getCursor(self):
        return self.db.getCursor()

    def insertOrReplaceStatement(self, insert, cur, tname, columns, *values):
        """
        """
        verb = "INSERT" if insert else "REPLACE"
        try:
            placeholder = ','.join("?" * len(values))
            stmt = "{} INTO {}({}) VALUES({})".format(verb, tname, columns,
                                                      placeholder)
            #result = cur.execute(stmt, [*values])
            result = cur.execute(stmt, flatten(*values))
            return cur.lastrowid
        except sqlite3.DatabaseError as e:
            excText = str(e)
            msg = "{} - Table: '{}'; Data: {}".format(excText, tname, values)
            self.logger.debug(msg)
            if excText.startswith("UNIQUE constraint failed:"):
                ii = excText.find(":")
                raise DuplicateKeyError(
                    "Table: '{}'; Key-Column: '{}'; Data: {}".format(
                        tname, excText[ii + 2:], values)) from None
            else:
                raise

    def insertStatement(self, cur, tname, columns, *values):
        """
        """
        return self.insertOrReplaceStatement(True, cur, tname, columns,
                                             *values)

    def replaceStatement(self, cur, tname, columns, *values):
        """
        """
        return self.insertOrReplaceStatement(False, cur, tname, columns,
                                             *values)

    def addCANCluster(self, name, comment):
        """
        """

    def addLINCluster(self, name, comment):
        """
        """

    def writeDbcFile(self, network=None, filename=None):
        """
        """
        pass

    def outputDbc(self, network, filename=None):
        """
        """
        dbcData = self.renderDbc(network)
        if filename:
            with open(os.fsencode(filename),
                      "w",
                      encoding="latin-1",
                      newline="\r\n") as outf:
                outf.write(dbcData)
        else:
            print(dbcData)

    def renderDbc(self, network):
        """
        """
        namespace = dict(db=self.queries)
        res = renderTemplateFromText(self.DBC_TEMPLATE,
                                     namespace,
                                     formatExceptions=True)
        return res

    ##
    ## Attribute stuff.
    ##
    def addAttributeDefinition(self,
                               name,
                               objectType,
                               valueType,
                               defaultValue,
                               limits,
                               enumValues=None,
                               comment=None):
        cur = self.getCursor()
        minimum = limits.min
        maximum = limits.max
        if valueType in (ValueType.FLOAT, ValueType.INT, ValueType.FLOAT):
            # TODO: type-check!
            defaultNumber = defaultValue
            defaultString = None
        else:
            defaultString = defaultValue
            defaultNumber = None
        self.insertStatement(
            cur, "Attribute_Definition",
            """Name, Objecttype, Valuetype, Minimum, Maximum,
            Enumvalues, Default_Number, Default_String, Comment""", name,
            objectType, valueType, minimum, maximum, enumValues, defaultNumber,
            defaultString, comment)
        return self.attributeDefinition(name)

    def attributeDefinitions(self, glob=None, regex=None):
        """
        """
        for item in self._searchTableForName("Attribute_Definition", glob,
                                             regex):
            yield AttributeDefinition.create(self.db, item)

    def attributeDefinition(self, name):
        """
        """
        cur = self.db.getCursor()
        where = "Name = '{}'".format(name)
        item = self.db.fetchSingleRow(cur,
                                      tname="Attribute_Definition",
                                      column="*",
                                      where=where)
        if item:
            return AttributeDefinition.create(self.db, item)
        else:
            return None

    def applicableAttributes(self, objectType):
        """
        """
        if not objectType in AttributeType.__members__.values():
            self.logger.error(
                "applicableAttributes(): invalid objecttype '{}'.".format(
                    objectType))
            return None
        cur = self.db.getCursor()
        yield from self.db.fetchFromTable(
            cur,
            "Attribute_Definition",
            where="objecttype = {}".format(objectType))

    def singleAttribute(self, objectType, name):
        """
        """
        if not objectType in AttributeType.__members__.values():
            self.logger.error(
                "applicableAttributes(): invalid objecttype '{}'.".format(
                    objectType))
            return None
        cur = self.db.getCursor()
        return self.db.fetchSingleRow(
            cur,
            "Attribute_Definition",
            column="*",
            where="objecttype = {} AND Name = '{}'".format(objectType, name))

    def attributeValue(self, oid, attrDef):
        cur = self.db.getCursor()
        return self.db.fetchSingleRow(
            cur,
            "Attribute_Value",
            column="*",
            where="Object_ID = {} AND Attribute_Definition = {}".format(
                oid, attrDef))

    ##
    ## EnvVar Stuff.
    ##
    def addEnvVar(self,
                  name,
                  vartype,
                  valueRange,
                  unit,
                  initialValue=None,
                  accessNodes=None):
        """
        """
        pass

    def envVar(self, name):
        """
        """
        cur = self.db.getCursor()
        where = "Name = '{}'".format(name)
        item = self.db.fetchSingleRow(cur,
                                      tname="EnvVar",
                                      column="*",
                                      where=where)
        if item:
            return EnvVar(self, item['RID'], item['Name'],
                          EnvVarType(item['Type']), item['Unit'],
                          EnvVarAccessType(item['Access'] & 0x0f),
                          item['Size'], item['Startup_Value'],
                          Limits(item['Minimum'],
                                 item['Maximum']), item['Comment'])
        else:
            return None

    def envVars(self, glob=None, regex=None):
        """
        """
        for item in self._searchTableForName("EnvVar", glob, regex):
            yield EnvVar(self, item['RID'], item['Name'],
                         EnvVarType(item['Type']), item['Unit'],
                         EnvVarAccessType(item['Access'] & 0x0f), item['Size'],
                         item['Startup_Value'],
                         Limits(item['Minimum'],
                                item['Maximum']), item['Comment'])

    ##
    ## Message stuff.
    ##
    def addMessage(self, name, identifier, size, comment=None):
        """Add a new message to database.

        Parameters
        ----------
        name : str
            Message name needs to unique within the database and a valid C identifier.
        identifier : int
            CAN identifier.
        size : int
            Size of message in bytes.
        comment : str
            Arbitrary description of the node.

        Returns
        -------
        `pydbc.api.message.Message`
            newly created Message object on success else None.

        Raises
        ------
        `pydbc.exceptions.DuplicateKeyError`
            If a message with the same name already exists.
        """
        cur = self.getCursor()
        self.insertStatement(cur, "Message", "Name, Message_ID, DLC, Comment",
                             name, identifier, size, comment)
        return self.message(name)

    def messages(self, glob=None, regex=None):
        """
        """
        for item in self._searchTableForName("Message", glob, regex):
            yield Message(self, item['RID'], item['Name'],
                          CANAddress(item['Message_ID']), item['DLC'],
                          item['Comment'])

    def message(self, name):
        """
        """
        cur = self.db.getCursor()
        where = "Name = '{}'".format(name)
        item = self.db.fetchSingleRow(cur,
                                      tname="Message",
                                      column="*",
                                      where=where)
        if item:
            return Message(self, item['RID'], item['Name'], item['Message_ID'],
                           item['DLC'], item['Comment'])
        else:
            return None

    def messageSignal(self, messageId, signalId):
        cur = self.db.getCursor()
        where = "Message = {} AND Signal = {}".format(messageId, signalId)
        return self.db.fetchSingleRow(cur,
                                      tname="Message_Signal",
                                      column="*",
                                      where=where)

    ##
    ## Node stuff.
    ##
    def addNode(self, name, comment=None):
        """Add a Node to the database.

        Parameters
        ----------
        name : str
            Node name needs to unique within the database and a valid C identifier.
        comment : str
            Arbitrary description of the node.

        Returns
        -------
            `pydbc.api.node.Node`
            newly created Node object on success else None.
        """
        cur = self.getCursor()
        self.insertStatement(cur, "Node", "Name, Comment", name, comment)
        return self.node(name)

    def nodes(self, glob=None, regex=None):
        """
        """
        for item in self._searchTableForName("Node", glob, regex):
            yield Node(self, item['RID'], item['Name'], item['Comment'])

    def node(self, name):
        """
        """
        cur = self.db.getCursor()
        where = "Name = '{}'".format(name)
        item = self.db.fetchSingleRow(cur,
                                      tname="Node",
                                      column="*",
                                      where=where)
        if item:
            return Node(self, item['RID'], item['Name'], item['Comment'])
        else:
            return None
###

    def addCategory(self):
        """
        """
        pass

    def addValuetable(self):
        """
        """
        pass

    ##
    ## Misc. stuff.
    ##
    def _searchTableForName(self,
                            tableName,
                            glob=None,
                            regex=None,
                            additionalWhereClause=None):
        """
        """
        if glob is None and regex is None:
            where = None
        elif glob is not None:
            where = "Name GLOB '{}'".format(glob)
        elif regex is not None:
            where = "Name REGEXP '{}'".format(regex)
        if where is not None and additionalWhereClause is not None:
            where = "{} AND {}".format(where, additionalWhereClause)
        cur = self.db.getCursor()
        return self.db.fetchFromTable(cur, tableName, where=where)
Beispiel #12
0
 def __init__(self, db):
     self.db = db
     self.logger = Logger(__name__)
Beispiel #13
0
 def __init__(self, database, logLevel = 'INFO', *args, **kws):
     super(DbcListener, self).__init__(database, logLevel, *args, **kws)
     self.logger = Logger(__name__, level = logLevel)
     self.bake_queries()
     self.insertNetwork()
Beispiel #14
0
class DbcListener(parser.BaseListener):
    """

    """

    def __init__(self, database, logLevel = 'INFO', *args, **kws):
        super(DbcListener, self).__init__(database, logLevel, *args, **kws)
        self.logger = Logger(__name__, level = logLevel)
        self.bake_queries()
        self.insertNetwork()

    def bake_queries(self):
        self.MESSAGE_BY_MESSAGE_ID = self.bakery(lambda session: session.query(Message).filter(Message.message_id == bindparam('message_id')))
        self.ENVVAR_BY_NAME = self.bakery(lambda session: session.query(EnvVar).filter(EnvVar.name == bindparam('name')))
        self.ENVDATA_BY_NAME = self.bakery(lambda session: session.query(EnvironmentVariablesData).filter(
            EnvironmentVariablesData.name == bindparam('name')))
        self.MESSAGE_SIGNAL_BY_NAME = self.bakery(lambda session: session.query(Signal.rid).join(Message_Signal).join(Message).\
                filter(Message.message_id == bindparam('messageID'), Signal.name == bindparam('signal_name')))
        self.NETWORK_BY_RID = self.bakery(lambda session: session.query(Network).filter(Network.rid == bindparam('rid')))
        self.SIGNAL_BY_RID = self.bakery(lambda session: session.query(Signal).filter(Signal.rid == bindparam('rid')))
        self.EXISTS_ATTRIBUTE_DEFINITION = self.bakery(lambda session: session.query(literal(True)).filter(
            Attribute_Definition.name == bindparam('name')))
        self.EXISTS_ATTRIBUTE_VALUE = self.bakery(lambda session: session.query(literal(True)).filter(
                Attribute_Value.object_id == bindparam('rid'), Attribute_Value.attribute_definition_id == bindparam('ad')))
        self.EXISTS_NETWORK = self.bakery(lambda session: session.query(literal(True)).filter(Network.name == bindparam('name')))
        self.EXISTS_NODE_RXSIGNAL = self.bakery(lambda session: session.query(literal(True)).filter(
                Node_RxSignal.node_id == bindparam('nodeId'),
                Node_RxSignal.message_id == bindparam('messageId'),
                Node_RxSignal.signal_id == bindparam('signalId')))
        self.EXISTS_VALUE_DESCRIPTION = self.bakery(lambda session: session.query(literal(True)).filter(
                Value_Description.valuetable_id == bindparam('rid'), Value_Description.value == bindparam('value')))
        self.MESSAGE_SIGNAL_BY_NAME2 = self.bakery(lambda session: session.query(Signal).join(Message_Signal).join(Message).\
            filter(Message.message_id == bindparam('messageID'), Signal.name == bindparam('signalName')))

    def getAttributeType(self, value):
        ATS = {
            "NETWORK": AttributeType.NETWORK,
            "BU": AttributeType.NODE,
            "BO": AttributeType.MESSAGE,
            "SG": AttributeType.SIGNAL,
            "EV": AttributeType.ENV_VAR,
            "REL_NODE": AttributeType.REL_NODE,
            "REL_SIGNAL": AttributeType.REL_SIGNAL,
            "REL_ENV_VAR": AttributeType.REL_ENV_VAR,
        }
        return ATS.get(value)

    def get_signal_by_name(self, messageID, signal_name):
        res = self.MESSAGE_SIGNAL_BY_NAME(self.session).params(messageID = messageID,signal_name = signal_name).first()
        if res:
            return res.rid
        else:
            self.logger.error("Message signal '{}'::'{}' does not exist.".format(messageID, signal_name))
            return []

    def insertReceivers(self, messageId, signalId, receiver):
        for rcv in receiver:
            res = self.NODE_BY_NAME(self.session).params(name = rcv).first()
            if res:
                nodeId = res.rid
            else:
                self.logger.error("While inserting signal receivers: node '{}' does not exist.".format(rcv))
                continue
            exists = self.EXISTS_NODE_RXSIGNAL(self.session).params(nodeId = nodeId, messageId = messageId,
                signalId = signalId).first()
            if exists:
                self.logger.error("While inserting signal receivers: receiver messageId: {} signalId: {} nodeId: {} already exists.".
                    format(messageId, signalId, nodeId)
                )
            else:
                rxs = Node_RxSignal(node_id = nodeId, message_id = messageId, signal_id = signalId)
                self.session.add(rxs)
        self.session.flush()

    def insertValueDescription(self, rid, description):
        objs = []
        for desc, value in description:
            exists = self.EXISTS_VALUE_DESCRIPTION(self.session).params(rid = rid, value = value).first()
            if exists:
                pass
            else:
                vd = Value_Description(valuetable_id = rid, value = value, value_description = desc)
                objs.append(vd)
        self.session.add_all(objs)
        self.session.flush()

    def insertAttributeDefinitions(self, ctx):
        self.log_insertion("AttributeDefinitions")
        ctx.value = [x.value for x in ctx.items]
        for attr in ctx.value:
            attrType = attr['type']
            name = attr['name']
            vt = attr['value']['type']
            values = attr['value']['value']
            minimum = None
            maximum = None
            enumvalues = None
            defaultNumber = None
            defaultString = None
            if attrType == 'BU_':
                objType = AttributeType.NODE
            elif attrType == 'BO_':
                objType = AttributeType.MESSAGE
            elif attrType == 'SG_':
                objType = AttributeType.SIGNAL
            elif attrType == 'EV_':
                objType = AttributeType.ENV_VAR
            elif attrType is None:
                objType = AttributeType.NETWORK
            elif attrType == 'BU_BO_REL_':
                objType = AttributeType.REL_NODE
            elif attrType == 'BU_SG_REL_':
                objType = AttributeType.REL_SIGNAL
            elif attrType == 'BU_EV_REL_':
                objType = AttributeType.REL_ENV_VAR
            if vt == 'INT':
                valueType = ValueType.INT
                minimum, maximum = values
            elif vt == 'HEX':
                valueType = ValueType.HEX
                minimum, maximum = values
            elif vt == 'FLOAT':
                valueType = ValueType.FLOAT
                minimum, maximum = values
            elif vt == 'STRING':
                valueType = ValueType.STRING
            elif vt == 'ENUM':
                valueType = ValueType.ENUM
                enumvalues = ';'.join(values)
            exists = self.EXISTS_ATTRIBUTE_DEFINITION(self.session).params(name = name).first()
            if exists:
                self.logger.error("While inserting attribute definitions: an attribute definition named '{}' already exists.".format(name))
            else:
                ad = Attribute_Definition(name = name, objecttype = objType, valuetype = valueType, minimum = minimum,
                                          maximum = maximum, enumvalues = enumvalues)
                self.session.add(ad)
        self.session.flush()

    def insertAttributeDefaults(self, ctx):
        self.log_insertion("AttributeDefaults")
        defaults = {}
        for item in ctx.items:
            name, value = item.value
            defaults[name] = value
            ad = self.ATTRIBUTE_DEFINITION_BY_NAME(self.session).params(name = name).first()
            if not ad:
                self.logger.error("While inserting attribute default values: attribute '{}' does not exist.".format(name))
                continue
            if ad.valuetype in (ValueType.INT, ValueType.HEX, ValueType.FLOAT):
                ad.default_number = value
            elif ad.valuetype in (ValueType.STRING, ValueType.ENUM):
                ad.default_string = value
        self.session.flush()
        ctx.value = defaults

    def insertNetwork(self, specific = None):
        self.log_insertion("Network")
        name = self.db.dbname
        exists = self.EXISTS_NETWORK(self.session).params(name = name).first()
        if exists:
            self.logger.error("While inserting network: an network named '{}' already exists.".format(name))
            return
        network = Network(name = name)
        self.session.add(network)
        proto = Vndb_Protocol(network = network, name = BusType.CAN.name, specific = specific)
        self.session.add(proto)
        self.session.flush()
        self.network_id = network.rid

    def exitDbcfile(self, ctx):
        self.session.commit()
        self.value = dict(
            version = ctx.version().value,
            newSymbols = ctx.newSymbols().value,
            bitTiming = ctx.bitTiming().value,
            nodes = ctx.nodes().value,
            valueTables = ctx.valueTables().value,
            messages = ctx.messages().value,
            messageTransmitters = ctx.messageTransmitters().value,
            environmentVariables = ctx.environmentVariables().value,
            environmentVariablesData = ctx.environmentVariablesData().value,
            signalTypes = ctx.signalTypes().value,
            comments = ctx.comments().value,
            attributeDefinitions = ctx.attributeDefinitions().value,
            relativeAttributeDefinitions = ctx.relativeAttributeDefinitions().value,
            attributeDefaults = ctx.attributeDefaults().value,
            relativeAttributeDefaults = ctx.relativeAttributeDefaults().value,
            attributeValues = ctx.attributeValues().value,
            relativeAttributeValues = ctx.relativeAttributeValues().value,
            objectValueTables = ctx.objectValueTables().value,
            categoryDefinitions = ctx.categoryDefinitions().value,
            categories = ctx.categories().value,
            signalGroups = ctx.signalGroups().value,
            signalExtendedValueTypeList = ctx.signalExtendedValueTypeList().value

        )

    def exitMessageTransmitters(self, ctx):
        self.log_insertion("NodeTxMessages")
        ctx.value = [x.value for x in ctx.items]
        for transmitter in ctx.value:
            msg = self.MESSAGE_BY_MESSAGE_ID(self.session).params(message_id = transmitter['messageID']).first()
            if not msg:
                self.logger.error("While inserting message transmitters: message '{}' does not exist.".format(transmitter['messageID']))
                continue
            for name in transmitter['transmitters']:
                node = self.NODE_BY_NAME(self.session).params(name = name).first()
                if not node:
                    self.logger.error("While inserting message transmitters: node '{}' does not exist.".format(name))
                    continue
                ntm = Node_TxMessage(node = node, message = msg)
                self.session.add(ntm)
        self.session.flush()

    def exitMessageTransmitter(self, ctx):
        transmitters = self.getValue(ctx.tx)
        ctx.value = dict(messageID = self.getValue(ctx.messageID), transmitters = transmitters)

    def exitSignalExtendedValueTypeList(self, ctx):
        self.log_insertion("SignalExtendedValueTypes")
        ctx.value = [x.value for x in ctx.items]
        valueTypes = ctx.value
        for item in valueTypes:
            msgId = item['messageID']
            sigName = item['signalName']
            vt = item['valueType']
            srid = self.get_signal_by_name(msgId, sigName)
            signal = self.SIGNAL_BY_RID(self.session).params(rid = srid).first()
            if not signal:
                self.logger.error("While inserting signal extended value types: signal '{}' does not exist.".format(srid))
                continue
            signal.valuetype = vt
        self.session.flush()

    def exitSignalExtendedValueType(self, ctx):
        messageID = self.getValue(ctx.messageID)
        signalName = self.getValue(ctx.signalName)
        valType = self.getValue(ctx.valType)
        if not valType in (0, 1, 2, 3):
            self.logger.error("While parsing signal extended value type: value type must be in range [0..3] - got '{}', using 0.".format(valType))
            valType = 0
        ctx.value = dict(messageID = messageID, signalName = signalName, valueType = valType)

    def exitMessages(self, ctx):
        self.log_insertion("Messages and Signals")
        ctx.value = [x.value for x in ctx.items]
        for msg in ctx.value:
            name = msg['name']
            mid = msg['messageID']
            dlc = msg['dlc']
            signals = msg['signals']
            transmitter = msg['transmitter']
            tx_node = self.NODE_BY_NAME(self.session).params(name = transmitter).first()
            if not tx_node:
                self.logger.error("While inserting messages: node '{}' does not exist.".format(transmitter))
                continue
            mm = Message(name = name, message_id = mid, dlc = dlc, sender = tx_node.rid)
            self.session.add(mm)
            for signal in signals:
                name = signal['name']
                startBit = signal['startBit']
                signalSize = signal['signalSize']
                byteOrder = signal['byteOrder']
                sign = signal['sign']
                factor = signal['factor']
                offset = signal['offset']
                minimum = signal['minimum']
                maximum = signal['maximum']
                unit = signal['unit']
                receiver = signal['receiver']
                multiplexorSignal = None
                multiplexDependent = None
                multiplexorValue = None
                multiplexerIndicator = signal['multiplexerIndicator']
                if multiplexerIndicator:
                    match = CO_MPX.match(multiplexerIndicator)
                    if match:
                        gd = match.groupdict()
                        #print("MPX:", gd)
                        gd['multiplexed'] == 'm'
                        multiplexorValue = gd['value']
                        multiplexorSignal = 1 if gd['multiplexer'] == 'M' else 0
                        multiplexDependent = 0 if multiplexorSignal else 1

                    """
                    multiplexorSignal = 1 if multiplexerIndicator == 'M' else 0
                    if multiplexorSignal:
                        multiplexDependent = 0
                        multiplexorValue = None
                    else:
                        multiplexDependent = 1

                        try:
                            multiplexorValue = int(multiplexerIndicator[1 : ])
                        except Exception as e:
                            print(str(e), "MPX:", multiplexerIndicator)
                else:
                    multiplexorSignal = None
                    multiplexDependent = None
                    multiplexorValue = None
                     """

                ss = Signal(name = name, bitsize = signalSize, byteorder = byteOrder, sign = sign,
                    formula_factor = factor, formula_offset = offset, minimum = minimum, maximum = maximum, unit = unit
                )
                self.session.add(ss)
                srid = ss.rid
                ms = Message_Signal(offset = startBit, multiplexor_signal = multiplexorSignal,
                    multiplex_dependent = multiplexDependent, multiplexor_value = multiplexorValue,
                    signal = ss, message = mm)
                self.session.add(ms)
                self.session.flush()
                self.insertReceivers(mm.rid, ss.rid, receiver)

    def exitMessage(self, ctx):
        ctx.value = dict(messageID = self.getValue(ctx.messageID), name = self.getValue(ctx.messageName),
            dlc = self.getValue(ctx.messageSize), transmitter = self.getTerminal(ctx.transmt),
            signals = [x.value for x in ctx.sgs]
        )

    def exitSignal(self, ctx):
        byteOrder = self.getValue(ctx.byteOrder)
        if not byteOrder in (0, 1):
            self.logger.error("While parsing signal: Error while parsing signal '{}': byteorder must be either 0 or 1 -- using 0".format(ctx.signalName.value))
            byteOrder = 0
        name = self.getValue(ctx.signalName)
        startBit = self.getValue(ctx.startBit)
        signalSize = self.getValue(ctx.signalSize)
        st = self.getTerminal(ctx.sign)
        sign = None if st is None else -1 if st == '-' else +1
        factor = self.getValue(ctx.factor)
        offset = self.getValue(ctx.offset)
        minimum = self.getValue(ctx.minimum)
        maximum = self.getValue(ctx.maximum)
        unit = self.getValue(ctx.unit)
        receiver = self.getValue(ctx.rcv) or []
        ctx.value = dict(name = name, startBit = startBit, signalSize = signalSize,
            byteOrder = byteOrder, sign = sign, factor = factor, offset = offset,
            minimum = minimum, maximum = maximum, unit = unit, receiver = receiver,
            multiplexerIndicator = ctx.mind.value if ctx.mind else None
        )

    def exitReceiver(self, ctx):
        ctx.value = [ctx.fid.text] + [x.value for x in ctx.ids]

    def exitTransmitter(self, ctx):
        ctx.value = [x.value for x in ctx.ids]

    def exitMultiplexerIndicator(self, ctx):
        ctx.value = self.getValue(ctx.mind)

    def exitValueTables(self, ctx):
        self.log_insertion("ValueTables")
        ctx.value = [x.value for x in ctx.items]
        for table in ctx.value:
            name = table['name']
            description = table['description']
            vt = Valuetable(name = name)
            self.session.add(vt)
            self.session.flush()
            self.insertValueDescription(vt.rid, description)
        self.session.flush()

    def exitValueTable(self, ctx):
        ctx.value = dict(name = ctx.name.value, description = [x.value for x in ctx.desc])

    def exitValueDescription(self, ctx):
        ctx.value = (ctx.name.value, ctx.val.value, )

    def exitNodes(self, ctx):
        self.log_insertion("Nodes")
        ctx.value = [x.value for x in ctx.ids]
        nodeSet = set(['Vector__XXX'])
        for name in ctx.value:
            if not name in nodeSet:
                nn = Node(name = name)
                self.session.add(nn)
            nodeSet.add(name)
        self.session.flush()

    def exitBitTiming(self, ctx):
        ctx.value = dict(baudrate = self.getValue(ctx.baudrate), btr1 = self.getValue(ctx.btr1), btr2 = self.getValue(ctx.btr2))

    def exitNewSymbols(self, ctx):
        ctx.value = [x.text for x in ctx.ids]

    def exitVersion(self, ctx):
        self.log_insertion("Versions")
        ctx.value = self.getValue(ctx.vs)
        version = ctx.value
        network = self.network_id
        vers = Dbc_Version(version_string = version, network = network)
        self.session.add(vers)
        self.session.flush()

    def exitObjectValueTables(self, ctx):
        self.log_insertion("ObjectValuetables")
        ctx.value = [x.value for x in ctx.items]
        for table in ctx.value:
            tp = table['type']
            description = table['description']
            if tp == 'SG':
                object_rid = table['messageID']
                name = table['signalName']
                otype = 0
            elif tp == 'EV':
                name = table['envVarName']
                otype = 1
                env_var = self.ENVVAR_BY_NAME(self.session).params(name = name).first()
                if not env_var:
                    self.logger.error("While inserting object value tables: environment variable '{}' does not exist.".format(name))
                    continue
                object_rid = env_var.rid
            vt = Valuetable(name = name)
            self.session.add(vt)
            self.session.flush()
            ovt = Object_Valuetable(object_type= otype, object_rid = object_rid, valuetable_id = vt.rid)
            self.session.add(ovt)
            self.session.flush()
            self.insertValueDescription(vt.rid, description)

    def exitObjectValueTable(self, ctx):
        items = [x.value for x in ctx.items]
        if ctx.messageID:
            messageID = ctx.messageID.value
            signalName = ctx.signalName.value
            di = dict(messageID = messageID, signalName = signalName)
            tp = "SG"
        else:
            envVarName = ctx.envVarName.value
            di = dict(envVarName = envVarName)
            tp = "EV"
        ctx.value = dict(type = tp, description = items, **di)

    def exitEnvironmentVariables(self, ctx):
        self.log_insertion("EnvVars")
        # TODO: Process after EVDATA!!!
        ctx.value = [x.value for x in ctx.evs]
        for var in ctx.value:
            unit = var['unit']
            initialValue = var['initialValue']
            accessNodes = var['accessNodes']
            accessType = var['accessType']
            minimum = var['minimum']
            maximum = var['maximum']
            envId = var['envId']
            varType = var['varType']
            name = var['name']
            env_data = self.ENVDATA_BY_NAME(self.session).params(name = name).first()
            if not env_data:
                #self.logger.error("Environment variable data '{}' does not exist.".format(name))
                #continue
                dataSize = 0
            else:
                dataSize = env_data.value
            envVar = EnvVar(name = name, type = varType, unit = unit, minimum = minimum, maximum = maximum,
                access = accessType, startup_value = initialValue, size = dataSize)
            self.session.add(envVar)
            for node in accessNodes:
                nn = self.NODE_BY_NAME(self.session).params(name = node).first()
                if not nn:
                    self.logger.error("While inserting environment variables: node '{}' does not exist.".format(name))
                    continue
                envVar.accessingNodes.append(nn)
        self.session.flush()

    def exitEnvironmentVariable(self, ctx):
        accessType = extractAccessType(ctx.DUMMY_NODE_VECTOR().getText())

        ctx.value = dict(name = self.getValue(ctx.name), varType = self.getValue(ctx.varType),
            minimum = self.getValue(ctx.minimum), maximum = self.getValue(ctx.maximum), unit = self.getValue(ctx.unit),
            initialValue = self.getValue(ctx.initialValue), envId = self.getValue(ctx.envId),
            accessType = accessType, accessNodes = self.getValue(ctx.accNodes)
        )

    def exitAccessNodes(self, ctx):
        nodes = [x.value for x in ctx.items]
        ctx.value = nodes

    def exitEnvironmentVariablesData(self, ctx):
        self.log_insertion("EnvironmentVariablesData")
        ctx.value = [x.value for x in ctx.evars]
        for item in ctx.value:
            print("EVD", item)
            name = item['name']
            value = item['value']
            evd = EnvironmentVariablesData(name = name, value = value)
            self.session.add(evd)
        self.session.flush()

    def exitEnvironmentVariableData(self, ctx):
        ctx.value = dict(name = self.getValue(ctx.varname), value = self.getValue(ctx.value))

    def exitSignalTypes(self, ctx):
        self.log_insertion("SignalTypes")
        ctx.value =[x.value for x in ctx.sigTypes]
        print("SIGNAL-TYPES", ctx.value)

    def exitSignalType(self, ctx):
        ctx.value = dict(name = self.getValue(ctx.signalTypeName), size = self.getValue(ctx.signalSize),
            byteOrder = self.getValue(ctx.byteOrder), valueType = self.getValue(ctx.valueType),
            factor = self.getValue(ctx.factor), offset = self.getValue(ctx.offset), minimum = self.getValue(ctx.minimum),
            maximum = self.getValue(ctx.maximum), unit = self.getValue(ctx.unit), defaultValue = self.getValue(ctx.defaultValue),
            valTable = self.getValue(ctx.valTable),
        )

    def exitComments(self, ctx):
        self.log_insertion("Comments")
        ctx.value = [x.value for x in ctx.items]
        for comment in ctx.value:
            tp = comment['type']
            text = comment['comment']
            key = comment['key']
            if tp == 'BU':
                obj = self.NODE_BY_NAME(self.session).params(name = key).first()
                if not obj:
                    self.logger.error("While inserting comments: node '{}' does not exist.".format(key))
                    continue
                obj.comment = text
            elif tp == 'BO':
                obj = self.MESSAGE_BY_MESSAGE_ID(self.session).params(message_id = key).first()
                if not obj:
                    self.logger.error("While inserting comments: message '{}' does not exist.".format(key))
                    continue
                obj.comment = text
            elif tp == 'SG':
                rid = self.get_signal_by_name(*key)
                if not rid:
                    self.logger.error("While inserting comments: message signal '{}' does not exist.".format(key))
                    continue
                obj = self.session.query(Signal).filter(Signal.rid == rid).first()
                obj.comment = text
            elif tp == 'EV':
                obj = self.ENVVAR_BY_NAME(self.session).params(name = key).first()
                if not obj:
                    self.logger.error("While inserting comments: environment variable '{}' does not exist.".format(key))
                    continue
                obj.comment = text
            else:   # NW !?
                obj = self.NETWORK_BY_RID(self.session).params(rid = self.network_id).first()
                if not obj:
                    self.logger.error("While inserting comments: network '{}' does not exist.".format(self.network_id))
                    continue
                obj.comment = text
        self.session.flush()

    def exitComment(self, ctx):
        comment = self.getValue(ctx.s)
        if ctx.c0:
            tp = "BU"
            key = self.getValue(ctx.c0)
        elif ctx.i1:
            tp = "BO"
            key = self.getValue(ctx.i1)
        elif ctx.i2:
            tp = "SG"
            key = (self.getValue(ctx.i2), self.getValue(ctx.c2), )
        elif ctx.c3:
            tp = "EV"
            key = self.getValue(ctx.c3)
        else:
            tp = "NETWORK"
            key = None
        ctx.value = dict(type = tp, key = key, comment = comment)

    def exitAttributeDefinitions(self, ctx):
        self.insertAttributeDefinitions(ctx)

    def exitAttributeDefinition(self, ctx):
        objectType = self.getTerminal(ctx.objectType)
        attributeName = self.getValue(ctx.attrName)
        attributeValue = self.getValue(ctx.attrValue)
        ctx.value = dict(type = objectType, name = attributeName, value = attributeValue)

    def exitRelativeAttributeDefinitions(self, ctx):
        ctx.value = [x.value for x in ctx.items]
        self.insertAttributeDefinitions(ctx)

    def exitRelativeAttributeDefinition(self, ctx):
        objectType = self.getTerminal(ctx.objectType)
        attributeName = self.getValue(ctx.attrName)
        attributeValue = self.getValue(ctx.attrValue)
        ctx.value = dict(type = objectType, name = attributeName, value = attributeValue)

    def exitAttributeValueType(self, ctx):
        if ctx.i00:
            tp = "INT"
            value = (self.getValue(ctx.i00), self.getValue(ctx.i01), )
        elif ctx.i10:
            tp = "HEX"
            value = (self.getValue(ctx.i10), self.getValue(ctx.i11), )
        elif ctx.f0:
            tp = "FLOAT"
            value = (float(self.getValue(ctx.f0)), float(self.getValue(ctx.f1)), )
        elif ctx.s0:
            tp = "STRING"
            value = None
        elif ctx.efirst:
            tp = "ENUM"
            efirst = [self.getValue(ctx.efirst)]
            eitems = [x.value for x in ctx.eitems]
            value = efirst + eitems
        ctx.value = dict(type = tp, value = value)

    def exitAttributeDefaults(self, ctx):
        self.insertAttributeDefaults(ctx)

    def exitAttributeDefault(self, ctx):
        name = self.getValue(ctx.n)
        value = self.getValue(ctx.v)
        ctx.value = (name, value)

    def exitRelativeAttributeDefaults(self, ctx):
        self.insertAttributeDefaults(ctx)

    def exitRelativeAttributeDefault(self, ctx):
        name = self.getValue(ctx.n)
        value = self.getValue(ctx.v)
        ctx.value = (name, value)

    def exitAttributeValue(self, ctx):
        if ctx.s:
            ctx.value = self.getValue(ctx.s)
        elif ctx.n:
            ctx.value = self.getValue(ctx.n)

    def exitAttributeValues(self, ctx):
        self.log_insertion("AttributeValues")
        ctx.value = [x.value for x in ctx.items]
        values = []
        for attr in ctx.value:
            stringValue = None
            numValue = None
            value = attr['attributeValue']
            if isinstance(value, str):
                stringValue = value
            else:
                numValue = value
            aname = attr['name']
            ad = self.ATTRIBUTE_DEFINITION_BY_NAME(self.session).params(name = attr['name']).first()
            if not ad:
                self.logger.error("While inserting attribute values: attribute definition named '{}' does not exist.".format(attr['name']))
                continue
            attrType = self.getAttributeType(attr['attributeType'])
            if attrType == AttributeType.MESSAGE:
                key = attr['messageID']
                msg = self.MESSAGE_BY_MESSAGE_ID(self.session).params(message_id = key).first()
                if not msg:
                    self.logger.error("While inserting attribute values: message '{}' does not exist.".format(key))
                    continue
                rid = msg.rid
            elif attrType == AttributeType.SIGNAL:
                key = attr['messageID'], attr['signalName'],
                rid = self.get_signal_by_name(*key)
            elif attrType == AttributeType.NODE:
                key = attr['nodeName']
                node = self.NODE_BY_NAME(self.session).params(name = key).first()
                if not node:
                    self.logger.error("While inserting attribute values: node '{}' does not exist.".format(key))
                    continue
                rid = node.rid
            elif attrType == AttributeType.ENV_VAR:
                key = attr['envVarname']
                envvar = self.ENVVAR_BY_NAME(self.session).params(name = key).first()
                if not envvar:
                    self.logger.error("While inserting attribute values: environment variable '{}' does not exist.".format(key))
                    continue
                rid = envvar.rid
            elif attrType == AttributeType.NETWORK:
                key = ''
                rid = 0
            else:
                rid = 0
                key = ''
            exists = self.EXISTS_ATTRIBUTE_VALUE(self.session).params(rid = rid, ad = ad.rid).first()
            if exists:
                self.logger.error("While inserting attribute values: attribute value for {} {} {} already exists.".format(AttributeType.SIGNAL.name, key, ad.name))
            else:
                av = Attribute_Value(object_id = rid, attribute_definition = ad, num_value = numValue, string_value = stringValue)
                values.append(av)
        self.session.add_all(values)
        self.session.flush()

    def exitAttributeValueForObject(self, ctx):
        attributeName = self.getValue(ctx.attributeName)
        if ctx.nodeName:
            nodeName = self.getValue(ctx.nodeName)
            attrValue = self.getValue(ctx.buValue)
            di = dict(attributeType = 'BU', nodeName = nodeName)
        elif ctx.mid1:
            mid1 = self.getValue(ctx.mid1)
            attrValue = self.getValue(ctx.boValue)
            di = dict(attributeType = 'BO', messageID = mid1)
        elif ctx.mid2:
            mid2 = self.getValue(ctx.mid2)
            signalName = self.getValue(ctx.signalName)
            attrValue = self.getValue(ctx.sgValue)
            di = dict(attributeType = 'SG', messageID = mid2, signalName = signalName)
        elif ctx.evName:
            evName = self.getValue(ctx.evName)
            attrValue = self.getValue(ctx.evValue)
            di = dict(attributeType = 'EV', envVarname = evName)
        else:
            evName = None
            attrValue = self.getValue(ctx.attrValue)
            di = dict(attributeType = "NETWORK")
        ctx.value = dict(name = attributeName, attributeValue = attrValue, **di)

    def exitRelativeAttributeValues(self, ctx):
        self.log_insertion("RelativeAttributeValues")
        items = [x.value for x in ctx.items]
        ctx.value = items
        for attr in items:
            attributeName = attr['attributeName']
            attributeValue = attr['attributeValue']
            attrributeType = self.getAttributeType(attr['attributeType'])
            ad = self.ATTRIBUTE_DEFINITION_BY_NAME(self.session).params(name = attr['attributeName']).first()
            if not ad:
                self.logger.error("While inserting relative attribute values: attribute definition '{}' does not exist.".format(attr['attributeName']))
                continue
            node = self.NODE_BY_NAME(self.session).params(name = attr['nodeName']).first()
            if not ad:
                self.logger.error("While inserting relative attribute values: node '{}' does not exist.".format(attr['nodeName']))
                continue
            nodeId = node.rid
            parent = attr['parent']
            optOid1 = nodeId
            optOid2 = None
            stringValue = None
            numValue = None
            value = attr['attributeValue']
            if isinstance(value, str):
                stringValue = value
            else:
                numValue = value
            if attrributeType == AttributeType.REL_SIGNAL:
                messageID = parent['messageID']
                optOid2 = messageID
                rid = self.get_signal_by_name(messageID, parent['signalName'])
                if not rid:
                    self.logger.error("While inserting relative attribute values: message signal '{}'::'{}' does not exist".format(messageID, parent['signalName']))
                    continue
            elif attrributeType == AttributeType.REL_ENV_VAR:
                evName = parent['evName']
                env_var = self.ENVVAR_BY_NAME(self.session).params(name = evName).first()
                if not env_var:
                    self.logger.error("While inserting relative attribute values: environment variable '{}' does not exist.".format(evName))
                    continue
                rid = env_var.rid
                #optOid2 = ???
            elif attrributeType == AttributeType.REL_NODE:
                messageID = parent['messageID']
                optOid2 = messageID
                msg = self.MESSAGE_BY_MESSAGE_ID(self.session).params(message_id = messageID).first()
                if not msg:
                    self.logger.error("While inserting relative attribute values: message '{}' does not exist.".format(messageID))
                    continue
                rid = msg.rid
            arv = AttributeRel_Value(object_id = rid, attribute_definition = ad, num_value = numValue,
                string_value = stringValue, opt_object_id_1 = optOid1, opt_object_id_2 = optOid2
            )
            self.session.add(arv)
        self.session.flush()

    def exitRelativeAttributeValueForObject(self, ctx):
        attrType = self.getTerminal(ctx.attrType)
        attributeName = self.getValue(ctx.attributeName)
        nodeName = self.getValue(ctx.nodeName)
        if attrType == "BU_BO_REL_":
            messageID = self.getValue(ctx.nodeAddress)
            attributeType = "REL_NODE"
            parent = dict(messageID = messageID)
            attrValue = self.getValue(ctx.attrValue)
        elif attrType == "BU_SG_REL_":
            messageID = self.getValue(ctx.messageID)
            signalName = self.getValue(ctx.signalName)
            attributeType = "REL_SIGNAL"
            parent = dict(messageID = messageID, signalName = signalName)
            attrValue = self.getValue(ctx.attrValue)
        elif attrType == "BU_EV_REL_":
            evName = ctx.evName.value
            attributeType = "REL_ENV_VAR"
            parent = dict(evName = evName)
            attrValue = self.getValue(ctx.evValue)
        ctx.value = dict(
            attributeType = attributeType, attributeName = attributeName, attributeValue = attrValue,
            nodeName = nodeName, parent = parent
        )

    def exitSignalGroups(self, ctx):
        self.log_insertion("SignalGroups")
        items = [x.value for x in ctx.items]
        ctx.value = items
        for group in ctx.value:
            messageID = group['messageID']
            gValue = group['gvalue']
            signalNames = group['signals']
            groupName = group['groupName']
            msg = self.MESSAGE_BY_MESSAGE_ID(self.session).params(message_id = messageID).first()
            if not msg:
                self.logger.error("While inserting signal groups: message '{}' does not exist.".format(messageID))
                continue
            sg = Signal_Group(name = groupName, value = gValue, message = msg)
            self.session.add(sg)
            self.session.flush()
            for signalName in signalNames:
                signal = self.MESSAGE_SIGNAL_BY_NAME2(self.session).params(messageID = messageID, signalName = signalName).first()
                if not signal:
                    self.logger.error("While inserting signal groups: message signal '{}'::'{}' does not exist.".format(messageID, signalName))
                    continue
                sgs = Signal_Group_Signal(signal_group = sg, message = msg, signal = signal)
                self.session.add(sgs)
        self.session.flush()

    def exitSignalGroup(self, ctx):
        messageID = self.getValue(ctx.messageID)
        groupName = self.getValue(ctx.groupName)
        gvalue = self.getValue(ctx.gvalue)
        signals = [x.value for x in ctx.signals]
        ctx.value = dict(messageID = messageID, groupName = groupName, gvalue = gvalue, signals = signals)

    def exitCategoryDefinitions(self, ctx):
        self.log_insertion("CategoryDefinitions")
        ctx.value = [x.value for x in ctx.items]
        for category in ctx.value:
            print("CAT-DEF", category)
            cd = Category_Definition(name = category['name'], key = category['category'], level = category['value'])
            self.session.add(cd)
        self.session.flush()

    def exitCategoryDefinition(self, ctx):
        ctx.value = dict(name = self.getValue(ctx.name), category = self.getValue(ctx.cat), value = self.getValue(ctx.num))

    def exitCategories(self, ctx):
        self.log_insertion("Categories")
        ctx.value = [x.value for x in ctx.items]
        for category in ctx.value:
            print("CAT-VALUE", category)
            attrType = category['type']
            catId = category['category']
            if attrType == 'BU':
                nodeName = category['nodeName']
                objType = CategoryType.NODE
                node = self.NODE_BY_NAME(self.session).params(node = nodeName).first()
                if not node:
                    self.logger.error("While inserting categories: node '{}' does not exist.".format(nodeName))
                    continue
                rid = node.rid
            elif attrType == 'BO':
                objType = CategoryType.MESSAGE
                messageID = category['messageID']
                msg = self.MESSAGE_BY_MESSAGE_ID(self.session).params(message_id = messageID).first()
                if not msg:
                    self.logger.error("While inserting categories: message '{}' does not exist.".format(messageID))
                    continue
                rid = msg.rid
            elif attrType == 'EV':
                envVarname = category['envVarname']
                objType = CategoryType.ENV_VAR
                env_var = self.ENVVAR_BY_NAME(self.session).params(name = envVarname)
                if not env_var:
                    self.logger.error("While inserting categories: environment variable '{}' does not exist.".format(envVarname))
                    continue
                rid = env_var.rid
            cv = Category_Value(object_id = rid, category_definition_id = catId, objecttype = objType)
            self.session.add(cv)
            print(cv)
        self.session.flush()

    def exitCategory(self, ctx):
        category = self.getValue(ctx.cat)
        if ctx.nodeName:
            nodeName = self.getValue(ctx.nodeName)
            di = dict(type = 'BU', nodeName = nodeName)
        elif ctx.mid1:
            mid1 = self.getValue(ctx.mid1)
            di = dict(type = 'BO', messageID = mid1)
        elif ctx.evName:
            evName = self.getValue(ctx.evName)
            di = dict(type = 'EV', envVarname = evName)
        ctx.value = dict(category = category, **di)
Beispiel #15
0
class CanDatabase(object):
    """

    """

    def __init__(self, filename = ":memory:", inMemory = False, cachesize = 4, logLevel = 'INFO'):
        self._name,_ = os.path.splitext(filename)
        if inMemory:
            self._dbname = ":memory:"
        else:
            if not filename.lower().endswith(DB_EXTENSION):
                self._dbname = "{}.{}".format(filename, DB_EXTENSION)
            else:
                self._dbname = filename
        self._filename = filename
        self.conn = sqlite3.connect(self.dbname, isolation_level = None)
        self.conn.create_function("REGEXP", 2, regexer)
        self.conn.isolation_level = None
        self.cachesize = cachesize
        self.setPragmas()
        self._filename = filename
        self.logger = Logger('db', level = logLevel)

    def __del__(self):
        self.conn.close()

    def close(self):
        self.conn.close()

    @property
    def name(self):
        return self._name

    @property
    def dbname(self):
        return self._dbname

    @property
    def filename(self):
        return self._filename

    def getCursor(self):
        return self.conn.cursor()

    def setPragma(self, cur, key, value):
        cur.execute("PRAGMA {} = {}".format(key, value))

    def setPragmas(self):
        cur = self.getCursor()
        self.setPragma(cur, "FOREIGN_KEYS", "ON")
        self.setPragma(cur, "PAGE_SIZE", "{}".format(PAGE_SIZE))
        self.setPragma(cur, "CACHE_SIZE", "{}".format(calculateCacheSize(self.cachesize * 1024 * 1024)))
        self.setPragma(cur, "SYNCHRONOUS", "OFF")   # FULL
        self.setPragma(cur, "LOCKING_MODE", "EXCLUSIVE")    # NORMAL
        self.setPragma(cur, "TEMP_STORE", "MEMORY") # FILE
        """

        #self.cur.execute('PRAGMA journal_mode = MEMORY')   # TRUNCATE
        #self.cur.execute('PRAGMA journal_mode = WAL')
        """

    def beginTransaction(self):
        self.conn.execute("BEGIN TRANSACTION")

    def commitTransaction(self):
        self.conn.commit()

    def rollbackTransaction(self):
        self.conn.rollback()

    def createDictFromRow(self, row, description):
        names = [d[0] for d in description]
        di = dict(zip(names, row))
        return di

    def fetchSingleRow(self, cur, tname, column, where):
        cur.execute("""SELECT {} FROM {} WHERE {}""".format(column, tname, where))
        row = cur.fetchone()
        if row is None:
            return []
        return self.createDictFromRow(row, cur.description)

    def fetchSingleValue(self, cur, tname, column, where):
        cur.execute("""SELECT {} FROM {} WHERE {}""".format(column, tname, where))
        result = cur.fetchone()
        if result is None:
            return None
        return result[0]

    def updateStatement(self, cur, tname, columns, where, *values):
        columns = [c.strip() for c in columns.split(",")]
        colStmt = ', '.join(["{} = ?".format(c) for c in columns])
        sql = "UPDATE OR FAIL {} SET {} WHERE {}".format(tname, colStmt, where)
        try:
            res = cur.execute(sql, *values)
        except sqlite3.DatabaseError as e:
            excText = str(e)
            msg = "{} - Table: '{}'; Data: {}".format(excText, tname, values)
            self.logger.debug(msg)
            if excText.startswith("UNIQUE constraint failed:"):
                ii = excText.find(":")
                raise DuplicateKeyError("Table: '{}'; Key-Column: '{}'; Data: {}".format(tname, excText[ii + 2 : ], values)) from None
            else:
                raise

    def insertOrReplaceStatement(self, insert, cur, tname, columns, *values):
        """
        """
        verb = "INSERT OR FAIL" if insert else "REPLACE"
        try:
            placeholder = ','.join("?" * len(values))
            stmt = "{} INTO {}({}) VALUES({})".format(verb, tname, columns, placeholder)
            cur.execute(stmt, flatten(*values))
            #cur.execute(stmt, *values)
        except sqlite3.DatabaseError as e:
            msg = "{} - Data: {}".format(str(e), values)
            self.logger.error(msg)
            return None
        else:
            return cur.lastrowid

    def insertStatement(self, cur, tname, columns, *values):
        return self.insertOrReplaceStatement(True, cur, tname, columns, *values)

    def replaceStatement(self, cur, tname, columns, *values):
        return self.insertOrReplaceStatement(False, cur, tname, columns, *values)

    def fetchFromTable(self, cur, tname, columns = None, where = None, orderBy = None):
        whereClause = "" if not where else "WHERE {}".format(where)
        orderByClause = "ORDER BY rowid" if not orderBy else "ORDER BY {}".format(orderBy)
        columnsClause = columns if columns else "*"
        result = cur.execute("""SELECT {} FROM {} {} {}""".format(columnsClause, tname, whereClause, orderByClause), [])
        while True:
            row = cur.fetchone()
            if row is None:
                return
            else:
                yield self.createDictFromRow(row, cur.description)
Beispiel #16
0
 def __init__(self, database, logLevel='INFO', *args, **kws):
     super(NcfListener, self).__init__(database, logLevel, *args, **kws)
     self.logger = Logger(__name__, level=logLevel)
Beispiel #17
0
class LdfListener(parser.BaseListener):

    def __init__(self, database, logLevel = 'INFO', *args, **kws):
        super(LdfListener, self).__init__(database, logLevel, *args, **kws)
        self.logger = Logger(__name__, level = logLevel)
        self.nodes = {}
        self.signals = {}
        self.frames = {}
        self.event_trigged_frames = []
        self.bake_queries()
        self.insertNetwork()

    def bake_queries(self):
        self.UNCONDITIONAL_FRAME_BY_NAME = self.bakery(lambda session: session.query(LinUnconditionalFrame).filter(
            LinUnconditionalFrame.name == bindparam("name")))
        self.SCHEDULE_TABLE_BY_NAME = self.bakery(lambda session: session.query(LinScheduleTable).filter(
            LinScheduleTable.name == bindparam('name')))
        self.ENCODING_TYPE_BY_NAME = self.bakery(lambda session: session.query(LinSignalEncodingType).filter(
            LinSignalEncodingType.name == bindparam("name")))
        self.LIN_NODE_BY_NAME = self.bakery(lambda session: session.query(LinNode).filter(LinNode.name == bindparam('name')))
        self.LIN_SIGNAL_BY_NAME = self.bakery(lambda session: session.query(LinSignal).filter(LinSignal.name == bindparam('name')))
        self.LIN_SIGNAL_BY_RID = self.bakery(lambda session: session.query(LinSignal).filter(LinSignal.rid == bindparam('rid')))

    def insertNetwork(self, specific = None):
        self.log_insertion("Network")
        network = LinNetwork(name = self.db.dbname)
        self.session.add(network)
        proto = Vndb_Protocol(network = network, name = BusType.LIN.name, specific = specific)
        self.session.add(proto)
        self.session.flush()
        self.network_id = network.lin_network_id

    def updateNetworkAttributes(self):
        value = self.value
        languageVersion = value['languageVersion']
        protocolVersion = value['protocolVersion']
        fileRevision = value['fileRevision']
        speed = value['speed']
        channelName = value['channelName']
        network = self.session.query(LinNetwork).filter(LinNetwork.lin_network_id == self.network_id).first()
        network.language_version = languageVersion
        network.protocol_version = protocolVersion
        network.file_revision = fileRevision
        network.speed = speed
        network.channel_name = channelName
        self.session.flush()

    def insertConfigurableFrames(self):
        self.log_insertion("ConfigurableFrames")
        for node, frames in self.configurableFrames.items():
            for frameName, messageID in frames:
                frame = self.UNCONDITIONAL_FRAME_BY_NAME(self.session).params(name = frameName).first()
                if not frame:
                    self.logger.error("While inserting configurable frames: frame '{}' does not exist.".format(frameName))
                    continue
                cf = LinConfigurableFrame(node = node, frame = frame, identifier = messageID)
                self.session.add(cf)
        self.session.flush()

    def insertFaultStateSignals(self):
        self.log_insertion("FaultStateSignals")
        for node, signals in self.faultStateSignals.items():
            for signalName in signals:
                signal = self.LIN_SIGNAL_BY_NAME(self.session).params(name = signalName).first()
                if not signal:
                    self.logger.error("While inserting fault state signals: signal '{}' does not exist.".format(signalName))
                    continue
                lfs = LinFaultStateSignal(node = node, signal = signal)
                self.session.add(lfs)
        self.session.flush()

    def insertResponseErrorSignals(self):
        self.log_insertion("ResponseErrorSignals")
        for node, signalName in self.responseErrorSignals.items():
            signal = self.LIN_SIGNAL_BY_NAME(self.session).params(name = signalName).first()
            if not signal:
                self.logger.error("While inserting response error signals: signal '{}' does not exist.".format(signalName))
                continue
            res = LinResponseErrorSignal(node = node, signal = signal)
            self.session.add(res)
        self.session.flush()

    def sendingFrameNames(self, signal):
        result = []
        for _, frame in self.frames.items():
            frameSignals = (s['signalName'] for s in frame['signals'])
            frameName = frame['frameName']
            if signal in frameSignals:
                result.append(frameName)
        return result

    def updateEventTriggeredFrames(self):
        for etf, name in self.event_trigged_frames:
            lst = self.SCHEDULE_TABLE_BY_NAME(self.session).params(name = name).first()
            if not lst:
                self.logger.error("While updating event triggered frames: schedult table '{}' does not exist.".format(name))
                continue
            etf.collision_resolving_schedule_table = lst
        self.session.flush()

    def exitLin_description_file(self, ctx):
        self.value = dict(
            protocolVersion = ctx.pv.value,
            languageVersion = ctx.lv.value,
            fileRevision = ctx.fr.value if ctx.fr else None,
            speed = ctx.ls.value,
            channelName = ctx.cn.value if ctx.cn else None,
            nodes = ctx.ndef.value,
            nodeCompositions = ctx.ncdef.value if ctx.ncdef else None,
            signals = ctx.sdef.value,
            diagnosticSignals = ctx.dsdef.value if ctx.dsdef else None,
            frames = ctx.fdef.value,
            sporadicFrames = ctx.sfdef.value if ctx.sfdef else [],
            eventTriggeredFrames = ctx.etfdef.value if ctx.etfdef else [],
            diagnosticFrames = ctx.dffdef.value if ctx.dffdef else [],
            nodeAttributes = ctx.nadef.value,
            scheduleTables = ctx.stdef.value,
            signalGroups = ctx.sgdef.value if ctx.sgdef else [],
            signalEncodings = ctx.setdef.value if ctx.setdef else [],
            signalRepresentations = ctx.srdef.value if ctx.srdef else [],
        )
        self.updateNetworkAttributes()
        self.insertConfigurableFrames()
        self.insertFaultStateSignals()
        self.insertResponseErrorSignals()
        self.updateEventTriggeredFrames()
        self.session.commit()

    def exitLin_protocol_version_def(self, ctx):
        ctx.value = self.getValue(ctx.s)

    def exitLin_language_version_def(self, ctx):
        ctx.value = self.getValue(ctx.s)

    def exitLin_file_revision_def(self, ctx):
        ctx.value = self.getValue(ctx.s)

    def exitLin_speed_def(self, ctx):
        ctx.value = self.getValue(ctx.n)

    def exitChannel_name_def(self, ctx):
        ctx.value = self.getValue(ctx.i)

    def exitNode_def(self, ctx):
        self.log_insertion("Nodes")
        mname = self.getValue(ctx.mname)
        timebase = self.getValue(ctx.tb)
        jitter = self.getValue(ctx.j)
        bit_length = self.getValue(ctx.bit_length)
        tolerant = self.getValue(ctx.tolerant)
        snames = [x.value for x in ctx.snames]
        ctx.value = dict(
            master = mname, timeBase = timebase, jitter = jitter, slaves = snames, bit_length = bit_length, tolerant = tolerant
        )
        nodes = ctx.value
        masterNode = nodes['master']
        master = LinMasterNode(name = masterNode, timebase = timebase, jitter = jitter, bit_length = bit_length, tolerant = tolerant)
        self.session.add(master)
        self.master_node = master
        self.session.flush()
        mrid = master.rid
        self.nodes[masterNode] = master
        self.master = masterNode
        for name in nodes['slaves']:
            slave = LinSlaveNode(name = name)
            self.session.add(slave)
            self.session.flush()    # ???
            srid = slave.lin_node_id
            self.nodes[name] = slave
        self.session.flush()

    def exitNode_attributes_def(self, ctx):
        self.log_insertion("NodeAttributes")
        items = [x.value for x in ctx.items]
        ctx.value = items
        attrs = ctx.value
        self.configurableFrames = {}
        self.faultStateSignals = {}
        self.responseErrorSignals = {}
        for attr in attrs:
            #print("ATTR:", attr)
            name = attr['name']
            node = self.nodes.get(name)
            if not node:
                self.logger.error("While inserting attribute definition: node '{}' does not exist.".format(name))
                continue
            node.protocol_version = attr['version']
            node.configured_NAD = attr['configuredNAD']
            node.initial_NAD = attr['initialNAD']
            node.supplier_id = attr['supplierID']
            node.function_id = attr['functionID']
            node.variant = attr['variant']
            node.p2_min = attr['p2Min']
            node.st_min = attr['stMin']
            node.n_as_timeout = attr['nAs']
            node.n_cr_timeout = attr['nCr']
            node.response_tolerance = attr['response_tolerance']
            if 'configurableFrames' in attr:
                self.configurableFrames[node] = []
                for cframe in attr['configurableFrames']:
                    self.configurableFrames[node].append((cframe['frameName'],cframe['messageID'], ))
            if 'faultStateSignals' in attr:
                self.faultStateSignals[node] = []
                for fs in attr['faultStateSignals']:
                    self.faultStateSignals[node].append(fs)
            if 'responseErrorSignal' in attr:
                res = attr['responseErrorSignal']
                self.responseErrorSignals[node] = res

        self.session.flush()

    def exitNode_attribute(self, ctx):
        name = self.getValue(ctx.name)
        version = self.getValue(ctx.version)
        n0 = self.getValue(ctx.n0)
        n1 = self.getValue(ctx.n1)
        attrs = self.getValue(ctx.attrs, dict())
        ctx.value = dict(name = name, version = version, configuredNAD = n0, initialNAD = n1, **attrs)

    def exitAttributes_def(self, ctx):
        sid = self.getValue(ctx.sid)
        fid = self.getValue(ctx.fid)
        v = self.getValue(ctx.v)
        sn0 = self.getValue(ctx.sn0)
        sn1s = [x.value for x in ctx.sn1s]
        cf = self.getValue(ctx.cf)
        p2Min = self.getValue(ctx.p2Min)
        stMin = self.getValue(ctx.stMin)
        nAs = self.getValue(ctx.nAs)
        nCr = self.getValue(ctx.nCr)
        response_tolerance = self.getValue(ctx.response_tolerance)
        ctx.value = dict(supplierID = sid, functionID = fid, variant = v, responseErrorSignal = sn0, faultStateSignals = sn1s,
            p2Min = p2Min, stMin = stMin, nAs = nAs, nCr = nCr, configurableFrames = cf, response_tolerance = response_tolerance
        )

    def exitConfigurable_frames(self, ctx):
        ctx.value = [x.value for x in ctx.frames]

    def exitConfigurable_frame(self, ctx):
        fname = self.getValue(ctx.fname)
        mid = self.getValue(ctx.mid)
        ctx.value = dict(frameName = fname, messageID = mid)

    def exitNode_composition_def(self, ctx):
        ctx.value = [x.value for x in ctx.items]

    def exitConfiguration(self, ctx):
        cname = self.getValue(ctx.cname)
        items = [x.value for x in ctx.items]
        ctx.value = dict(configurationName = cname, items = items)

    def exitConfiguration_item(self, ctx):
        cnode = self.getValue(ctx.cnode)
        lnodes = [x.value for x in ctx.lnodes]
        ctx.value = dict(compositeNode = cnode, logicalNodes = lnodes)

    def exitSignal_def(self, ctx):
        self.log_insertion("Signals")
        ctx.value = [x.value for x in ctx.items]
        for signal in ctx.value:
            #print("SIG:", signal)
            initValue = signal['initValue']
            name = signal['name']
            size = signal['size']
            publishedBy = signal['publishedBy']
            subscribedBy = signal['subscribedBy']
            publisher = self.nodes.get(publishedBy)
            if not publisher:
                self.logger.error("While inserting signals: publisher node '{}' does not exist.".format(publishedBy))
                continue
            if not initValue['scalar'] is None:
                iv = initValue['scalar']
            elif not initValue['array'] is None:
                iv = initValue['array']
            else:
                self.logger.error("While inserting signals: no initial value for signal '{}'.".format(name))
                iv = None
            sig = LinSignal(name = name, signal_size = size, init_value = iv, publisher = publisher)
            self.session.add(sig)

            for subscriber in subscribedBy:
                node = self.nodes.get(subscriber)
                if not node:
                    self.logger.error("While inserting signals: subscriber node '{}' does not exist.".format(subscriber))
                    continue
                sig.subscribers.append(node)
            self.session.flush()
            signal['rid'] = sig.rid
            self.signals[name] = signal
        #self.session.flush()

    def exitSignal_item(self, ctx):
        sname = self.getValue(ctx.sname)
        ssize = self.getValue(ctx.ssize)
        initValue = self.getValue(ctx.initValue)
        pub = self.getValue(ctx.pub)
        sub = [x.value for x in ctx.sub]
        ctx.value = dict(name = sname, size = ssize, initValue = initValue, publishedBy = pub, subscribedBy = sub)

    def exitInit_value(self, ctx):
        scalar = self.getValue(ctx.s)
        array = self.getValue(ctx.a)
        ctx.value = dict(scalar = scalar, array = array)

    def exitInit_value_scalar(self, ctx):
        ctx.value = self.getValue(ctx.i)

    def exitInit_value_array(self, ctx):
        ctx.value = [x.value for x in ctx.vs]

    def exitDiagnostic_signal_def(self, ctx):
        ctx.value = [x.value for x in ctx.items]

    def exitDiagnostic_item(self, ctx):
        name = self.getValue(ctx.name)
        size = self.getValue(ctx.size)
        initValue = self.getValue(ctx.initValue)
        ctx.value = dict(name = name, size = size, initValue = initValue)

    def exitSignal_groups_def(self, ctx):
        ctx.value = [x.value for x in ctx.items]

    def exitSignal_group(self, ctx):
        sgname = self.getValue(ctx.sgname)
        gsize = self.getValue(ctx.gsize)
        items = [x.value for x in ctx.items]
        ctx.value = dict(signalGroupName = sgname, groupSize = gsize, items = items)

    def exitSignal_group_item(self, ctx):
        sname = self.getValue(ctx.sname)
        goffs = self.getValue(ctx.goffs)
        ctx.value = dict(signalName = sname, groupOffset = goffs)

    def exitFrame_def(self, ctx):
        self.log_insertion("UnconditionalFrames")
        ctx.value = [x.value for x in ctx.items]
        for frame in ctx.value:
            frid = frame['frameID']
            name = frame['frameName']
            size = frame['frameSize']
            publishedBy = frame['publishedBy']
            publisher = self.nodes.get(publishedBy)
            if not publisher:
                self.logger.error("While inserting unconditional frames: node '{}' does not exist.".format(publishedBy))
                continue
            msg = LinUnconditionalFrame(name = name, frame_id = frid, size = size, publisher = publisher)
            self.session.add(msg)
            self.session.flush()
            #print("FRAME:", msg)
            frame['rid'] = msg.rid
            self.frames[name] = frame
            for signal in frame['signals']:
                signalOffs = signal['signalOffset']
                signalName = signal['signalName']
                srid = self.signals[signalName]['rid']
                sgn = self.LIN_SIGNAL_BY_RID(self.session).params(rid = srid).first()
                if not sgn:
                    self.logger.error("While inserting unconditional frames: signal '{}' does not exist.".format(srid))
                    continue
                msg.add_signal(sgn, signalOffs)
        self.session.flush()

    def exitFrame_item(self, ctx):
        fname = self.getValue(ctx.fname)
        fid = self.getValue(ctx.fid)
        p = self.getValue(ctx.p)
        fsize = self.getValue(ctx.fsize)
        items = [x.value for x in ctx.items]
        ctx.value = dict(frameName = fname, frameID = fid, publishedBy = p, frameSize = fsize, signals = items)

    def exitFrame_signal(self, ctx):
        sname = self.getValue(ctx.sname)
        soffs = self.getValue(ctx.soffs)
        ctx.value = dict(signalName = sname, signalOffset = soffs)

    def exitSporadic_frame_def(self, ctx):
        self.log_insertion("SporadicFrames")
        ctx.value = [x.value for x in ctx.items]
        for sf in ctx.value:
            #print("*SPOR", sf)
            name = sf['sporadicFrameName']
            lsf = LinSporadicFrame(name = name)
            self.session.add(lsf)
            self.session.flush()
            for frameName in sf['frameNames']:
                frame = self.MESSAGE_BY_NAME(self.session).params(name = frameName).first()
                if not frame:
                    self.logger.error("While inserting sporadic frames: frame '{}' does not exist.".format(frameName))
                    continue
                lsf.associated_frames.append(frame)
        self.session.flush()

    def exitSporadic_frame_item(self, ctx):
        name = ctx.sfn.value
        fnames = [x.value for x in ctx.names]
        ctx.value = dict(sporadicFrameName = name, frameNames = fnames)

    def exitEvent_triggered_frame_def(self, ctx):
        self.log_insertion("EventTriggeredFrames")
        ctx.value = [x.value for x in ctx.items]
        for ef in ctx.value:
            name = ef['frameName']
            scheduleTable = ef['scheduleTable']
            frameID = ef['frameID']
            etf = LinEventTriggeredFrame(name = name, master_node = self.master_node, frame_id = frameID)
            self.session.add(etf)
            self.event_trigged_frames.append((etf, scheduleTable))
            for frameName in ef['frameNames']:
                frame = self.MESSAGE_BY_NAME(self.session).params(name = frameName).first()
                if not frame:
                    self.logger.error("While inserting event triggered frames: frame '{}' does not exist.".format(frameName))
                    continue
                etf.associated_frames.append(frame)
        self.session.flush()

    def exitEvent_triggered_frame_item(self, ctx):
        e = self.getValue(ctx.e)
        c = self.getValue(ctx.c)
        fid = self.getValue(ctx.fid)
        items = [x.value for x in ctx.items]
        ctx.value = dict(frameName = e, frameID = fid, scheduleTable = c, frameNames = items)

    def exitDiag_frame_def(self, ctx):
        mid = self.getValue(ctx.mid)
        sid = self.getValue(ctx.sid)
        mitems = [x.value for x in ctx.mitems]
        sitems = [x.value for x in ctx.sitems]
        ctx.value = dict(masterID = mid, slaveID = sid, masterSignals = mitems, slaveSignals = sitems)

    def exitDiag_frame_item(self, ctx):
        sname = self.getValue(ctx.sname)
        soffs = self.getValue(ctx.soffs)
        ctx.value = dict(signalName = sname, signalOffset = soffs)

    def exitSchedule_table_def(self, ctx):
        self.log_insertion("ScheduleTables")
        ctx.value = [x.value for x in ctx.items]
        for table in ctx.value:
            name = table['name']
            lst = LinScheduleTable(name = name)
            self.session.add(lst)
            self.session.flush()
            for cmd in table['commands']:
                frame_time = cmd['frameTime']
                cmd = cmd['command']
                ct = cmd['type']
                if ct == 'Frame':
                    name = cmd['frame_name']
                    frame = self.MESSAGE_BY_NAME(self.session).params(name = name).first()
                    if not frame:
                        self.logger.error("While inserting schedule tables: frame '{}' does not exist.".format(name))
                        continue
                    entry = LinScheduleTable_Command_Frame(frame_time = frame_time, frame = frame)
                elif ct == 'MasterReq':
                    entry = LinScheduleTable_Command_MasterReq(frame_time = frame_time)
                elif ct == 'SlaveResp':
                    entry = LinScheduleTable_Command_SlaveResp(frame_time = frame_time)
                elif ct == 'AssignNAD':
                    node_name = cmd['node_name']
                    node = self.nodes.get(node_name)
                    if not node:
                        self.logger.error("While inserting schedule tables: node '{}' does not exist.".format(name))
                        continue
                    entry = LinScheduleTable_Command_AssignNad(frame_time = frame_time, node = node)
                elif ct == 'ConditionalChangeNAD':
                    nad = cmd['nad']
                    id_ = cmd['id']
                    byte_ = cmd['byte']
                    mask = cmd['mask']
                    inv = cmd['inv']
                    new_nad = cmd['new_nad']
                    entry = LinScheduleTable_Command_ConditionalChangeNad(frame_time = frame_time, nad = nad,
                        id = id_, byte = byte_, mask = mask, inv = inv, new_nad = new_nad
                    )
                elif ct == 'DataDump':
                    node_name = cmd['node_name']
                    node = self.nodes.get(node_name)
                    if not node:
                        self.logger.error("While inserting schedule tables: node '{}' does not exist.".format(name))
                        continue
                    d1 = cmd['d1']
                    d2 = cmd['d2']
                    d3 = cmd['d3']
                    d4 = cmd['d4']
                    d5 = cmd['d5']
                    entry = LinScheduleTable_Command_DataDump(frame_time = frame_time, node = node, d1 = d1,
                        d2 = d2, d3 = d3, d4 = d4, d5 = d5
                    )
                elif ct == 'SaveConfiguration':
                    node_name = cmd['node_name']
                    node = self.nodes.get(node_name)
                    if not node:
                        self.logger.error("While inserting schedule tables: node '{}' does not exist.".format(name))
                        continue
                    entry = LinScheduleTable_Command_SaveConfiguration(frame_time = frame_time, node = node)
                elif ct == 'AssignFrameIdRange':
                    node_name = cmd['node_name']
                    node = self.nodes.get(node_name)
                    if not node:
                        self.logger.error("While inserting schedule tables: node '{}' does not exist.".format(name))
                        continue
                    frame_index = cmd['frame_index']
                    frame_pid1 = cmd['pid1']
                    frame_pid2 = cmd['pid2']
                    frame_pid3 = cmd['pid3']
                    frame_pid4 = cmd['pid4']
                    entry = LinScheduleTable_Command_AssignFrameIdRange(frame_time = frame_time, node = node,
                        frame_index = frame_index, frame_pid1 = frame_pid1, frame_pid2 = frame_pid2,
                        frame_pid3 = frame_pid3, frame_pid4 = frame_pid4
                    )
                elif ct == 'FreeFormat':
                    d1 = cmd['d1']
                    d2 = cmd['d2']
                    d3 = cmd['d3']
                    d4 = cmd['d4']
                    d5 = cmd['d5']
                    d6 = cmd['d6']
                    d7 = cmd['d7']
                    d8 = cmd['d8']
                    entry = LinScheduleTable_Command_FreeFormat(frame_time = frame_time, d1 = d1, d2 = d2, d3 = d3,
                        d4 = d4, d5 = d5, d6 = d6, d7 = d7, d8 = d8
                    )
                elif ct == 'AssignFrameId':
                    node_name = cmd['nodeName']
                    frame_name = cmd['frameName']
                    node = self.nodes.get(node_name)
                    if not node:
                        self.logger.error("While inserting schedule tables: node '{}' does not exist.".format(name))
                        continue
                    frame = self.MESSAGE_BY_NAME(self.session).params(name = frame_name).first()
                    if not frame:
                        self.logger.error("While inserting schedule tables: frame '{}' does not exist.".format(frame_name))
                        continue
                    entry = LinScheduleTable_Command_AssignFrameId(frame_time = frame_time, node = node, frame = frame)
                self.session.add(entry)
                lst.entries.append(entry)
            self.session.flush()

    def exitSchedule_table_entry(self, ctx):
        s = self.getValue(ctx.s)
        items = [x.value for x in ctx.items]
        ctx.value = dict(name = s, commands = items)

    def exitSchedule_table_command(self, ctx):
        c = self.getValue(ctx.c)
        f = self.getValue(ctx.f)
        ctx.value = dict(command = c, frameTime = f)

    def exitCommand(self, ctx):
        if ctx.frameName:
            cmdName = "Frame"
        else:
            cmdName = ctx.c.text
        cmd = dict(type = cmdName)
        if cmdName == "Frame":
            cmd['frame_name'] = ctx.frameName.value
        elif cmdName == 'AssignNAD':
            cmd['node_name'] = ctx.nodeName.value
        elif cmdName == 'ConditionalChangeNAD':
            cmd['nad'] = ctx.nad.value
            cmd['id'] = ctx.id_.value
            cmd['byte'] = ctx.byte_.value
            cmd['mask'] = ctx.mask.value
            cmd['inv'] = ctx.inv.value
            cmd['new_nad'] = ctx.new_NAD.value
        elif cmdName == 'DataDump':
            cmd['node_name'] = ctx.nodeName.value
            cmd['d1'] = ctx.d1.value
            cmd['d2'] = ctx.d2.value
            cmd['d3'] = ctx.d3.value
            cmd['d4'] = ctx.d4.value
            cmd['d5'] = ctx.d5.value
        elif cmdName == 'SaveConfiguration':
            cmd['node_name'] = ctx.nodeName.value
        elif cmdName == 'AssignFrameIdRange':
            cmd['node_name'] = ctx.nodeName.value
            cmd['frame_index'] = ctx.frameIndex.value
            cmd['pid1'] = None
            cmd['pid2'] = None
            cmd['pid3'] = None
            cmd['pid4'] = None
            pids = [p.value for p in ctx.pids]
            lp = len(pids)
            if lp == 1:
                cmd['pid1'] = pids[0]
            elif lp == 2:
                cmd['pid1'] = pids[0]
                cmd['pid2'] = pids[1]
            elif lp == 3:
                cmd['pid1'] = pids[0]
                cmd['pid2'] = pids[1]
                cmd['pid3'] = pids[2]
            elif lp == 4:
                cmd['pid1'] = pids[0]
                cmd['pid2'] = pids[1]
                cmd['pid3'] = pids[2]
                cmd['pid4'] = pids[3]
        elif cmdName == 'FreeFormat':
            cmd['d1'] = ctx.d1.value
            cmd['d2'] = ctx.d2.value
            cmd['d3'] = ctx.d3.value
            cmd['d4'] = ctx.d4.value
            cmd['d5'] = ctx.d5.value
            cmd['d6'] = ctx.d6.value
            cmd['d7'] = ctx.d7.value
            cmd['d8'] = ctx.d8.value
        elif cmdName == 'AssignFrameId':
            cmd['nodeName'] = ctx.nodeName.value
            cmd['frameName'] = ctx.frName.value
        ctx.value = cmd

    def exitSignal_encoding_type_def(self, ctx):
        self.log_insertion("SignalEncodings")
        items = [x.value for x in ctx.items]
        ctx.value = items
        tps = set()
        for enc in items:
            lse = LinSignalEncodingType(name = enc['name'])
            self.session.add(lse)
            for value in enc['values']:
                vtype = value['valueType']
                value = value["value"]
                if vtype == "logical":
                    entry = LinSignalEncodingEntry_Logical(signal_value = value['signalValue'], text_info = value['text'])
                elif vtype == "range":
                    min_value = value['min']
                    max_value = value['max']
                    scale = value['scale']
                    offset = value['offset']
                    text = value['text']
                    entry = LinSignalEncodingEntry_Physical(min_value = min_value, max_value = max_value,
                        scale = scale, offset = offset, text_info = text
                    )
                elif vtype == "bcd":
                    entry = LinSignalEncodingEntry_Value(entry_type = 2)
                elif vtype == "ascii":
                    entry = LinSignalEncodingEntry_Value(entry_type = 1)
                lse.entries.append(entry)
                self.session.add(entry)
        self.session.flush()

    def exitSignal_encoding_entry(self, ctx):
        s = self.getValue(ctx.s)
        items = [x.value for x in ctx.items]
        ctx.value = dict(name = s, values = items)


    def exitSignal_encoding_value(self, ctx):
        if ctx.l:
            value = self.getValue(ctx.l)
            vtype = "logical"
        elif ctx.p:
            value = self.getValue(ctx.p)
            vtype = "range"
        elif ctx.b:
            value = None
            vtype = "bcd"
        elif ctx.a:
            value = None
            vtype = "ascii"
        ctx.value = dict(value = value, valueType = vtype)

    def exitLogical_value(self, ctx):
        s = self.getValue(ctx.s)
        t = self.getValue(ctx.t)
        ctx.value = dict(signalValue = s, text = t)

    def exitPhysical_range(self, ctx):
        minValue = self.getValue(ctx.minValue)
        maxValue = self.getValue(ctx.maxValue)
        #scale = ctx.scale.value if ctx.scale else None
        #offset = ctx.offset.value
        scale = self.getValue(ctx.s)
        offset = self.getValue(ctx.o)
        t = self.getValue(ctx.t)
        ctx.value = dict(min = minValue, max = maxValue, scale = scale, offset = offset, text = t)

    def exitBcd_value(self, ctx):
        pass

    def exitAscii_value(self, ctx):
        pass

    def exitSignal_representation_def(self, ctx):
        self.log_insertion("SignalRepresentations")
        items = [x.value for x in ctx.items]
        ctx.value = items
        for sr in items:
            name = sr['name']
            lse = self.ENCODING_TYPE_BY_NAME(self.session).params(name = name).first()
            if not lse:
                self.logger.error("While inserting signal representations: encoding type '{}' does not exist.".format(name))
                continue
            for signal_name in sr['signalNames']:
                signal = self.LIN_SIGNAL_BY_NAME(self.session).params(name = signal_name).first()
                if not signal:
                    self.logger.error("While inserting signal representations: signal '{}' does not exist.".format(signal_name))
                    continue
                lsr = LinSignalRepresentation(signal_encoding_type = lse, signal = signal)
                self.session.add(lsr)
        self.session.flush()

    def exitSignal_representation_entry(self, ctx):
        enc = self.getValue(ctx.enc)
        names = [x.value for x in ctx.names]
        ctx.value = dict(name = enc, signalNames = names)