1- import traceback
2-
3- from converter import Converter , ConverterExternal
4- from schema_types import schema_language_from_string
5- from logic import build_conversion_graph , identify_schema_features , find_paths , rank_paths
1+ from conversion_strategies import convert_with_strategy_most_features_preserved , ConversionStrategy , \
2+ convert_with_strategy_least_character_loss
3+ from converter import ( Converter , ConverterExternal )
4+ from schema_types import schema_language_from_string , SchemaLanguagesFeatures
5+ from logic import build_conversion_graph , find_paths
66from register_converters import register_converters
77from flask import Flask , request
88from typing import List , Dict
9+ from schema_languages_loader import load_schema_language_features
910
1011app = Flask (__name__ )
1112
1213DETAILED_ERROR_OUTPUT = False
14+ CONVERSION_STRATEGY = ConversionStrategy .LeastCharacterLoss
1315
1416converters : List [Converter ] = register_converters ()
1517conversion_graph : Dict [str , List [Converter ]] = build_conversion_graph (converters )
18+ schema_languages_features : SchemaLanguagesFeatures = load_schema_language_features ()
19+
1620print ("Started Schema Conversion Orchestrator with the following converters:" )
1721for conv in converters :
1822 print (f"- { conv .name } : { conv .source_format } -> { conv .target_format } at { conv .service_address } " )
2226def health ():
2327 return {"status" : "ok" }, 200
2428
29+
2530@app .route ("/registerConversion" , methods = ["POST" ])
2631def register_conversion ():
2732 data = request .json
@@ -35,7 +40,8 @@ def register_conversion():
3540 converters .append (conv )
3641 global conversion_graph
3742 conversion_graph = build_conversion_graph (converters )
38- print (f"Registered new converter: { conv .name } from { conv .source_format } to { conv .target_format } at { conv .service_address } ." )
43+ print (
44+ f"Registered new converter: { conv .name } from { conv .source_format } to { conv .target_format } at { conv .service_address } ." )
3945 return {"status" : "registered" }, 200
4046
4147
@@ -58,52 +64,24 @@ def convert():
5864 if not all_paths :
5965 return {"error" : "No path found for conversion from source " + source + " to target " + target + "." }, 400
6066
61- doc_features = set (identify_schema_features (schema , source , conversion_graph ))
62- ranked_paths = rank_paths (all_paths , doc_features )
63- attempt_errors = []
64- result_schema = None
65-
66- # attempt conversion via best path and if it fails, try remaining paths and print error message only to console
67- # if no path is left, return the error messages of all attempts consolidated
68- # create only one loop and try and catch and do not treat the first path specially
69- while result_schema is None and len (ranked_paths ) > 0 :
70- best_path , unsupported_features = ranked_paths [0 ]
71- try :
72- result_schema = attempt_conversion_path (source , target , best_path , schema )
73- except Exception as e :
74- ranked_paths = ranked_paths [1 :]
75- if DETAILED_ERROR_OUTPUT :
76- full_traceback = traceback .format_exc ()
77- attempt_errors .append (f"Error: { e } \n Traceback:\n { full_traceback } " )
78- else :
79- attempt_errors .append (str (e ))
80-
81- if result_schema is None :
67+ if CONVERSION_STRATEGY == ConversionStrategy .MostFeaturesPreserved :
68+ attempts = convert_with_strategy_most_features_preserved (
69+ source , target , schema , all_paths )
70+ elif CONVERSION_STRATEGY == ConversionStrategy .LeastCharacterLoss :
71+ attempts = convert_with_strategy_least_character_loss (
72+ source , target , schema , all_paths )
73+ else :
74+ return {"error" : "Unknown conversion strategy: " + CONVERSION_STRATEGY }, 500
75+
76+ best_attempt = attempts [0 ]
77+ success , schema , conversion_path = best_attempt
78+
79+ if not success :
8280 # return error message of all attempts together with the attempt number (1 to n)
83- return {"error" : "All conversion paths failed. Details: " + " | " .join ([f"Attempt { i + 1 } : { msg } " for i , msg in enumerate (attempt_errors )])}, 500
84-
85- return {"schema" : result_schema }, 200
86-
87-
88- def attempt_conversion_path (source : str , target : str , path : List [Converter ], schema : str ) -> str :
89- print_conversion_path (source , target , path )
90- current_schema = schema
91- current_converter = None
92- try :
93- for conv in path :
94- current_converter = conv
95- current_schema = conv .convert (current_schema )
96- print ("Intermediate schema of format " + conv .target_format + " after conversion via " + conv .service_name + ": " + current_schema )
97- return current_schema
98- except Exception as e :
99- print ("Conversion failed at step from " + current_converter .source_format + " to " + current_converter .target_format + " via " + current_converter .service_name + " because of error: " + str (e ) + "." )
100- print ("With intermediate schema: " + current_schema )
101- raise Exception (f"Conversion failed at step from { current_converter .source_format } to { current_converter .target_format } via { current_converter .service_name } because of error: { str (e )} ." )
102-
103- def print_conversion_path (source : str , target : str , path : List [Converter ]) -> None :
104- print ("Given the source format " + source + " and target format " + target + ", the best available path is:" )
105- for conv in path :
106- print (f"{ conv .source_format } -> { conv .target_format } via { conv .name } ({ conv .service_address } )" )
81+ return {"error" : "All conversion paths failed." , attempts : attempts }, 500
82+
83+ return {"schema" : schema }, 200
84+
10785
10886def call_internal_converter (source : str , target : str , schema : str ) -> str :
10987 if source == "JsonSchema" and target == "LinkMl" :
@@ -113,5 +91,6 @@ def call_internal_converter(source: str, target: str, schema: str) -> str:
11391 else :
11492 raise Exception ("Unsupported internal conversion" )
11593
94+
11695if __name__ == "__main__" :
11796 app .run (host = "0.0.0.0" , port = 5002 )
0 commit comments