diff --git a/src/api/server.py b/src/api/server.py index 9b2aa59..2df4b50 100644 --- a/src/api/server.py +++ b/src/api/server.py @@ -1,7 +1,6 @@ """Implemenation of the REST-API endpoint.""" -from flask import Flask, request, jsonify, flash - +from flask import Flask, request, jsonify from src.components.logic.log_skeleton import Log_Skeleton from src.components.util.xes_importer \ import XES_Importer, TRACE_START, TRACE_END @@ -9,7 +8,6 @@ from flask_cors import CORS, cross_origin - __PARAMETERS__ = 'parameters' # HTTP Methods @@ -35,7 +33,7 @@ EVENT_LOG = 'event-log' FILE = 'file' -ALLOWED_EXTENSIONS = {'xes'} +ALLOWED_EXTENSIONS = {'xes', 'csv'} app = Flask(__name__) cors = CORS(app) @@ -64,19 +62,35 @@ def event_log(): if method == POST: if FILE not in request.files: - return jsonify({ 'error': "No selected file" }), __BAD_REQUEST__ + return jsonify({'error': "No selected file"}), __BAD_REQUEST__ file = request.files[FILE] if file.filename == '': - return jsonify({ 'error': "Empty files" }), __BAD_REQUEST__ + return jsonify({'error': "Empty files"}), __BAD_REQUEST__ if not allowed_file(file.filename): - return jsonify({ 'error': "File type not supported" }), __BAD_REQUEST__ + return jsonify({ + 'error': "File type not supported" + }), __BAD_REQUEST__ id = event_store.put_event_log(file) - return jsonify({'id': id}) - - return "Something is wrong" + importer = XES_Importer() + + try: + content = event_store.pull_event_log(id) + + log, activities = importer.import_str(content, [], []) + + return jsonify({ + 'id': id, + 'activities': list(activities) + }) + except: # noqa: E722 + return jsonify({ + 'error': "Could not import file." + }), __BAD_REQUEST__ + + return jsonify({'error': "Something is wrong"}) @app.route('/log-skeleton/', methods=['GET', 'POST']) @@ -156,13 +170,13 @@ def apply(id, req): required = [] try: - path = event_store.pull_event_log(id) + content = event_store.pull_event_log(id) log, all_activities = \ - importer.import_file(path, - forbidden, - required, - extended_trace=include_extended_traces) + importer.import_str(content, + forbidden, + required, + extended_trace=include_extended_traces) except: # noqa: E722 return {'error_msg': 'Unable to import XES log. \ @@ -191,6 +205,8 @@ def apply(id, req): return model, __OK__ -event_store.start_event_store() -app.run() - +# event_store.start_event_store() +# app.run() +if __name__ == "__main__": + print('Server running!...') + app.run(debug=True, host='0.0.0.0') diff --git a/src/components/logic/log_skeleton.py b/src/components/logic/log_skeleton.py index 5cda4e0..dbab31e 100644 --- a/src/components/logic/log_skeleton.py +++ b/src/components/logic/log_skeleton.py @@ -49,11 +49,11 @@ def set_activities(self, activities): self.all_activities = activities def get_activities(self): - """Return the current set of activities""" + """Return the current set of activities.""" return self.all_activities def set_working_relationships(self, working_relationships): - """Choose working set for the relationship + """Choose working set for the relationship. Parameters: working_relationships: A set or list of relationships as string @@ -73,7 +73,7 @@ def set_working_relationships(self, working_relationships): self.working_relationships.add(r) def get_working_relationships(self): - """Return current working set of relationships """ + """Return current working set of relationships.""" return self.working_relationships def apply(self): diff --git a/src/components/util/event_store.py b/src/components/util/event_store.py index 02811c4..2e1c6cd 100644 --- a/src/components/util/event_store.py +++ b/src/components/util/event_store.py @@ -11,6 +11,9 @@ import appdirs import time import _thread +from pm4py.objects.conversion.log import converter as log_conv +import pandas as pd +from pm4py.objects.log.exporter.xes import exporter as xes_exporter # App name for caching files __APP_NAME__ = 'Log-Skeleton-Backend' @@ -27,6 +30,8 @@ # Caching dir on the respective os cache_dir = appdirs.user_cache_dir(__APP_NAME__) +print(cache_dir) + # Make sure the cache dir exists if not os.path.exists(cache_dir): os.makedirs(cache_dir) @@ -78,13 +83,37 @@ def put_event_log(file) -> str: """Cache the event log.""" id = uuid.uuid4().hex - file.save(os.path.join(cache_dir, id + '.xes')) + # file.save(os.path.join(cache_dir, id + '.xes')) + + filename = file.filename + + if filename.endswith('csv'): + path = os.path.join(cache_dir, id + '.csv') + file.save(path) + + log_csv = pd.read_csv(path, sep=',') + # log_csv.rename(columns={'clientID': 'case:clientID'}, inplace=True) + parameters = {log_conv.Variants. + TO_EVENT_LOG.value.Parameters.CASE_ID_KEY: 'case'} + event_log = log_conv.apply(log_csv, + parameters=parameters, + variant=log_conv.Variants.TO_EVENT_LOG) + + xes_exporter.apply(event_log, os.path.join(cache_dir, id + '.xes')) + + with open(os.path.join(cache_dir, id + '.xes'), 'r') as f: + content = f.read().decode('utf-8') + + event_store[id] = content + + else: + content = file.read().decode('utf-8') - event_store[id] = id + '.xes' + event_store[id] = content - print('Storing file at: ' + id + '.xes') + print('Storing file at: ' + id) - __store_delete_time(id) + # __store_delete_time(id) return id @@ -92,9 +121,9 @@ def put_event_log(file) -> str: def pull_event_log(id): """Pull the event-log path from the storage.""" # Reschedule the deletion time of the event-log - __store_delete_time(id) + # __store_delete_time(id) - return os.path.join(cache_dir, event_store[id]) + return event_store[id] def event_log_garbage_collector():