Example #1
0
    def cache_extension(uri):
        """Downloads and caches an extension from its remote definition file.
        The extension is subsequently placed in the local cache, so that future
        loading is accelerated.

        :param uri: Unique URI of the extension which is to be cached.
        :type uri: urllib.parse.ParseResult or urllib.parse.SplitResult
        """
        uri_str = uri.geturl()
        if uri_str[-1] == "/":
            uri_str = uri_str[(0, len(uri_str) - 1)]
        filename = uri_str[uri_str.rindex(chr(47)):]
        if not filename.endswith(".xesext"):
            filename += ".xesext"

        cache_file = XRuntimeUtils().get_extension_cache_folder(
        ) + os.path.sep + filename

        try:
            bis = request.urlopen(uri.geturl())
            bos = open(cache_file, "w")

            file = bis.read(1024)
            while file != b"":
                bos.write(file)
                file = bis.read(1024)
            bos.close()
            XLogging().log("Cached XES extension \\'" + uri.geturl() + "\\'",
                           XLogging.Importance.DEBUG)

        except IOError as e:
            print("I/O error({0}): {1}".format(e.errno, e.strerror))
Example #2
0
    def load_extension_cache(self):
        """Loads all extensions stored in the local cache. Cached extensions
        which exceed the maximum caching age are discarded, and downloaded
        freshly.

        """
        min_modified = (lambda: int(round(time.time() * 1000)))() - 2592000000
        ext_folder = XRuntimeUtils().get_extension_cache_folder()
        ext_files = list(filter(os.path.isfile, os.listdir(ext_folder)))
        if len(ext_files) == 0:
            XLogging().log(
                "Extension caching disabled (Could not access cache"
                " directory)!", XLogging.Importance.WARNING)
            return

        for i in range(len(ext_files)):
            ext_file = ext_files[i]
            if ext_file.lower().endswith(".xesext"):
                file_name = ext_folder + os.path.sep + ext_file
                if os.path.getmtime(file_name) * 1000 < min_modified:
                    if os.path.exists(file_name):
                        os.remove(file_name)
                else:
                    try:
                        extension = XExtensionParser.parse(file_name)
                        if extension.get_uri() not in self.__extension_map:
                            self.__extension_map[
                                extension.get_uri()] = extension
                            self.__extension_list.append(extension)
                            XLogging().log(
                                "Loaded XES extension \'" +
                                extension.get_uri().geturl() + "\' from cache",
                                XLogging.Importance.DEBUG)
                        else:
                            XLogging().log(
                                "Skipping cached XES extension \'" +
                                extension.get_uri().geturl() +
                                "\' (already defined)",
                                XLogging.Importance.DEBUG)
                    except Exception as e:
                        print("Exception error: {}".format(e))
Example #3
0
        def endElement(self, local_name):
            """ Overrides endElement in class ContentHandler

            :param local_name: The name of the element type, just as with the startElement event
            :type local_name: str
            """
            tag_name = local_name

            if tag_name == "WorkflowLog":
                if self.__numUnorderedEntries > 0:
                    XLogging().log(
                        "LogData: Log contains " +
                        str(self.__numUnorderedEntries) +
                        " audit trail entries in non-natural order!",
                        XLogging.Importance.ERROR)
                    XLogging().log(
                        "LogData: The log file you have loaded is not MXML compliant! (error compensated transparently)",
                        XLogging.Importance.ERROR)

            elif tag_name == "Process":
                self.__currentProcess.get_classifiers().extend(
                    XMxmlParser.MXML_CLASSIFIERS)
                self.__currentProcess.get_global_trace_attributes().append(
                    XConceptExtension().ATTR_NAME.clone())
                self.__currentProcess.get_global_event_attributes().append(
                    XConceptExtension().ATTR_NAME.clone())
                self.__currentProcess.get_global_event_attributes().append(
                    XLifecycleExtension().ATTR_TRANSITION.clone())
                self.__logs.append(self.__currentProcess)
                self.__currentProcess = None

            elif tag_name == "Process":
                self.__sourceOpen = False

            elif tag_name == "ProcessInstance":
                if len(self.__currentInstance) > 0:
                    self.__currentProcess.append(self.__currentInstance)

                self.__currentInstance = None
                self.__lastTimestamp = None

            elif tag_name == "AuditTrailEntry":
                if self.__timestamp is None:
                    self.__currentInstance.append(self.__entry)
                elif self.__lastTimestamp is None:
                    self.__currentInstance.append(self.__entry)
                    self.__lastTimestamp = self.__timestamp
                elif self.__timestamp > self.__lastTimestamp:
                    self.__currentInstance.append(self.__entry)
                    self.__lastTimestamp = self.__timestamp
                else:
                    self.__currentInstance.append(self.__entry)

                self.__entry = None

            else:
                if tag_name == "Attribute":
                    originator = "".join(self.__buffer).strip()
                    if len(originator) > 0:
                        self.__genericAttribute.set_value("".join(
                            self.__buffer).strip())
                        if self.__entry:
                            self.__entry.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                        elif self.__currentInstance:
                            self.__currentInstance.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                        elif self.__currentProcess:
                            self.__currentProcess.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                        elif self.__sourceOpen:
                            self.__sourceAttribute.get_attributes()[
                                self.__genericAttribute.get_key(
                                )] = self.__genericAttribute
                    self.__genericAttribute = None

                elif tag_name == "EventType":
                    if self.__eventTypeAttribute.get_value() == "UNKNOWN":
                        originator = "".join(self.__buffer).strip()
                        if len(originator) > 0:
                            self.__eventTypeAttribute.set_value(originator)
                            self.__entry.get_attributes()[
                                self.__eventTypeAttribute.get_key(
                                )] = self.__eventTypeAttribute
                    else:
                        self.__entry.get_attributes()[
                            self.__eventTypeAttribute.get_key(
                            )] = self.__eventTypeAttribute
                    self.__eventTypeAttribute = None

                elif tag_name == "WorkflowModelElement":
                    XConceptExtension().assign_name(
                        self.__entry, "".join(self.__buffer).strip())

                elif tag_name == "Timestamp":
                    originator = "".join(self.__buffer).strip()
                    self.__timestamp = parse_date_time(originator)
                    if self.__timestamp:
                        timestamp_attribute = XTimeExtension(
                        ).ATTR_TIMESTAMP.clone()
                        timestamp_attribute.set_value(self.__timestamp)
                        self.__entry.get_attributes(
                        )[timestamp_attribute.get_key()] = timestamp_attribute

                elif tag_name == "Originator":
                    originator = "".join(self.__buffer).strip()
                    if len(originator) > 0:
                        self.__originatorAttribute.set_value(originator)

                    self.__entry.get_attributes()[
                        self.__originatorAttribute.get_key(
                        )] = self.__originatorAttribute
                    self.__originatorAttribute = None

            self.__buffer.clear()
Example #4
0
    def serialize(self, log, out, in_bytes=False):
        """Serializes a given log to the given output stream.

        :param log: Log to be serialized.
        :type log: `XLog`
        :param out:  TextIOWrapper for serialization.
        :type out: _io.TextIOWrapper
        :param in_bytes: Private argument to decide if serialized in bytes or in string
        :type in_bytes: bool
        """
        XLogging().log("start serializing log to MXML",
                       XLogging.Importance.DEBUG)
        start = time.time() * 1000

        root = Et.Element("WorkflowLog")
        source = Et.SubElement(root, "Source")
        source.set("program", "XES MXML serialization")
        source.set("openxes.version", "1.0RC7")
        process = Et.SubElement(root, "Process")
        identity = XConceptExtension().extract_name(log)
        if identity is None:
            process.set("id", "none")
        else:
            process.set("id", identity)
        name = XConceptExtension().extract_name(log)
        if name is None:
            name = "None"
        process.set("description", "process with id " + name)
        self.add_model_reference(log, process)
        self.add_attribute(process, log.get_attributes().values())

        for trace in log:
            instance = Et.SubElement(process, "ProcessInstance")
            identity = XConceptExtension().extract_name(trace)
            if identity is None:
                identity = "None"
            instance.set("id", identity)
            name = XConceptExtension().extract_name(trace)
            if name is None:
                name = "None"
            instance.set("description", "instance with id " + name)
            self.add_model_reference(trace, instance)
            self.add_attribute(instance, trace.get_attributes().values())

            for event in trace:
                ate = Et.SubElement(instance, "AuditTrailEntry")
                self.add_attribute(ate, event.get_attributes().values())
                workflow_mode = Et.SubElement(ate, "WorkflowModelElement")
                self.add_model_reference(event, workflow_mode)
                workflow_mode.text = XConceptExtension().extract_name(event)
                type_ = Et.SubElement(ate, "EventType")
                type_attr = event.get_attributes().get("lifecycle:transition")

                if type_attr:
                    self.add_model_reference(type_attr, type_)
                    originator_attr = type_attr.get_value().strip().lower()
                    if originator_attr in self.__known_types:
                        type_.text = originator_attr
                    else:
                        type_.set("unknownType", type_attr.get_value())
                        type_.text = "unknown"

                else:
                    type_.text = "complete"

                originator_attr_1 = event.get_attributes().get("org:resource")
                if originator_attr_1 is None:
                    originator_attr_1 = event.get_attributes().get("org:role")

                if originator_attr_1 is None:
                    originator_attr_1 = event.get_attributes().get("org:group")

                if originator_attr_1 is not None:
                    timestamp_attr = Et.SubElement(ate, "originator")
                    self.add_model_reference(originator_attr_1, timestamp_attr)
                    timestamp_attr.text = (originator_attr_1.get_value())

                timestamp_attr_1 = event.get_attributes().get("time:timestamp")
                if timestamp_attr_1:
                    timestamp = Et.SubElement(ate, "timestamp")
                    self.add_model_reference(timestamp_attr_1, timestamp)
                    date = timestamp_attr_1.get_value()
                    timestamp.text = str(date)

        text = minidom.parseString(Et.tostring(root, "utf-8"))
        c1 = text.createComment(
            "This file has been generated with the OpenXES library. It conforms"
        )
        c2 = text.createComment(
            "to the legacy MXML standard for log storage and management.")
        c3 = text.createComment("OpenXES library version: 1.0RC7")
        c4 = text.createComment(
            "OpenXES is available from http://www.xes-standard.org/")
        text.insertBefore(c4, text.childNodes[0])
        text.insertBefore(c3, text.childNodes[0])
        text.insertBefore(c2, text.childNodes[0])
        text.insertBefore(c1, text.childNodes[0])
        if in_bytes:
            out.write(text.toprettyxml("\t").encode())
        else:
            out.write(text.toprettyxml("\t"))

        duration1 = " (" + str(time.time() * 1000 - start) + " msec.)"
        XLogging().log("finished serializing log" + duration1,
                       XLogging.Importance.DEBUG)
Example #5
0
    def serialize(self, log, out, in_bytes=False):
        """Serializes a given log to the given output stream.

        :param log: Log to be serialized.
        :type log: XLog
        :param out: TextIOWrapper for serialization.
        :type out: _io.TextIOWrapper
        :param in_bytes: Private argument to decide if serialized as bytes or as string
        :type in_bytes: bool
        """
        XLogging().log("Start serializing log to XES.XML",
                       XLogging.Importance.DEBUG)
        start = time.time() * 1000

        log_xml = Et.Element("log")
        log_xml.set("xes.version", "1.0")
        log_xml.set("xes.features", "nested-attributes")
        log_xml.set("openxes.version", "1.0RC7")

        for extension in log.get_extensions():
            extension_xml = Et.SubElement(log_xml, "extension")
            extension_xml.set("name", extension.get_name())
            extension_xml.set("prefix", extension.get_prefix())
            extension_xml.set("uri", extension.get_uri().geturl())

        self.add_global_attributes(log_xml, "trace",
                                   log.get_global_trace_attributes())
        self.add_global_attributes(log_xml, "event",
                                   log.get_global_event_attributes())

        for classifier in log.get_classifiers():
            if isinstance(classifier, XEventAttributeClassifier):
                classifier_xml = Et.SubElement(log_xml, "classifier")
                classifier_xml.set("name", classifier.name())
                classifier_xml.set(
                    "keys",
                    XTokenHelper.format_token(
                        classifier.get_defining_attribute_keys()))

        self.add_attributes(log_xml, log.get_attributes().values())

        for trace in log:
            trace_xml = Et.SubElement(log_xml, "trace")
            self.add_attributes(trace_xml, trace.get_attributes().values())

            for event in trace:
                event_xml = Et.SubElement(trace_xml, "event")
                self.add_attributes(event_xml, event.get_attributes().values())

        text = minidom.parseString(Et.tostring(log_xml, "utf-8"))
        c1 = text.createComment(
            "This file has been generated with the OpenXES library. It conforms"
        )
        c2 = text.createComment(
            "to the XML serialization of the XES standard for log storage and")
        c3 = text.createComment("management.")
        c4 = text.createComment("XES standard version: 1.0")
        c5 = text.createComment("OpenXES library version: 1.0RC7")
        c6 = text.createComment(
            "OpenXES is available from http://www.openxes.org/")
        text.insertBefore(c6, text.childNodes[0])
        text.insertBefore(c5, text.childNodes[0])
        text.insertBefore(c4, text.childNodes[0])
        text.insertBefore(c3, text.childNodes[0])
        text.insertBefore(c2, text.childNodes[0])
        text.insertBefore(c1, text.childNodes[0])

        if in_bytes:
            out.write(text.toprettyxml("\t").encode())
        else:
            out.write(text.toprettyxml("\t"))

        duration1 = " (" + str(time.time() * 1000 - start) + " msec.)"
        XLogging().log("finished serializing log" + duration1,
                       XLogging.Importance.DEBUG)