Commit 221888cb authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ added JsonSchemaBridge to handle ASN.1 files and generated JSON schemas #29

+ corresponding CLI options
+ corresponding profile settings
+ integration in T3Q
* version number update
* refinement to resource provider (ignore individual input files that do not match pattern)
+ updated reference profiles
parent 8927b6e6
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -2,10 +2,11 @@
  <ConfigurationProfiles>
    <QualityCheckProfile>
      <profileName>stf160Profile</profileName>
      <profileVersion>v2.1.0b3</profileVersion>
      <profileVersion>v2.1.0b4</profileVersion>
      <!--  <resourceExtensionsRegExp>ttcn|ttcn3|3mp</resourceExtensionsRegExp> -->
      <!--    <projectExtension>t3p</projectExtension> -->
      <ignoredResourceRegExp>((.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)|(.*[/\\]Common[/\\](HTTP)[/\\]uri.*[.]ttcn)|(.*[/\\]LTE_A_R12[/\\](D2D_ProSe)[/\\]urn.*[.]ttcn)|(.*[/\\]IMS[/\\]XCAP_XSD[/\\].*[.]ttcn)|(.*[/\\]MCX[/\\]CommonXSD[/\\].*[.]ttcn)|(.*[/\\].*[/\\][Cc]ommon[/\\]TestcaseProperties.*[.]ttcn))</ignoredResourceRegExp>   
      <!-- added pattern for files generated from ASN.1 -->
      <ignoredResourceRegExp>((.*asn[.]json[.]ttcn)|(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)|(.*[/\\]Common[/\\](HTTP)[/\\]uri.*[.]ttcn)|(.*[/\\]LTE_A_R12[/\\](D2D_ProSe)[/\\]urn.*[.]ttcn)|(.*[/\\]IMS[/\\]XCAP_XSD[/\\].*[.]ttcn)|(.*[/\\]MCX[/\\]CommonXSD[/\\].*[.]ttcn)|(.*[/\\].*[/\\][Cc]ommon[/\\]TestcaseProperties.*[.]ttcn))</ignoredResourceRegExp>   
      <!--   <settingRecursiveProcessing>true</settingRecursiveProcessing>  -->
      <checkNoUninitializedFieldsInTemplates>true</checkNoUninitializedFieldsInTemplates>
      <checkNoUninitializedFieldsInTemplatesRecursion>false</checkNoUninitializedFieldsInTemplatesRecursion>
@@ -123,6 +124,8 @@
      </namingConventionsConfig>
      <dependencyOutputPath>DOCUMENTATION</dependencyOutputPath>
      <pathFormattedOutputPath>FORMATTED</pathFormattedOutputPath>
      <titanCompilerPath>compiler</titanCompilerPath>      
      <jsonSchemaPath></jsonSchemaPath>
      <!-- formattingParameters>
        <tabs>false</tabs>
        <unixNewline>false</unixNewline>
@@ -145,8 +148,8 @@
    </QualityCheckProfile>
    <QualityCheckProfile>
      <profileName>defaultProfile</profileName>
      <profileVersion>v2.1.0b3</profileVersion>
      <ignoredResourceRegExp>(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <profileVersion>v2.1.0b4</profileVersion>
      <ignoredResourceRegExp>(.*asn[.]json[.]ttcn)|(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <settingAbortOnError>true</settingAbortOnError>
      <loggingConfiguration>
        <showFullPath>false</showFullPath>
@@ -263,11 +266,13 @@
        <enumeratedValueRegExp>e_[a-z].*</enumeratedValueRegExp>
      </namingConventionsConfig>
      <pathFormattedOutputPath>FORMATTED</pathFormattedOutputPath>
      <titanCompilerPath>compiler</titanCompilerPath>
      <jsonSchemaPath></jsonSchemaPath>
    </QualityCheckProfile>
    <QualityCheckProfile>
      <profileName>nothing</profileName>
      <profileVersion>v2.1.0b3</profileVersion>
      <ignoredResourceRegExp>(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <profileVersion>v2.1.0b4</profileVersion>
      <ignoredResourceRegExp>(.*asn[.]json[.]ttcn)|(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <settingAbortOnError>true</settingAbortOnError>
      <loggingConfiguration>
        <showFullPath>false</showFullPath>
@@ -382,6 +387,8 @@
        <enumeratedValueRegExp>e_[a-z].*</enumeratedValueRegExp>
      </namingConventionsConfig>
      <pathFormattedOutputPath>FORMATTED</pathFormattedOutputPath>
      <titanCompilerPath>compiler</titanCompilerPath>      
      <jsonSchemaPath></jsonSchemaPath>
    </QualityCheckProfile>    
  </ConfigurationProfiles>
  <defaultConfigurationProfile>all</defaultConfigurationProfile>
+13 −6
Original line number Diff line number Diff line
@@ -2,10 +2,11 @@
  <ConfigurationProfiles>
    <QualityCheckProfile>
      <profileName>stf160Profile</profileName>
      <profileVersion>v2.1.0b3</profileVersion>
      <profileVersion>v2.1.0b4</profileVersion>
      <!--  <resourceExtensionsRegExp>ttcn|ttcn3|3mp</resourceExtensionsRegExp> -->
      <!--    <projectExtension>t3p</projectExtension> -->
      <ignoredResourceRegExp>((.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)|(.*[/\\]Common[/\\](HTTP)[/\\]uri.*[.]ttcn)|(.*[/\\]LTE_A_R12[/\\](D2D_ProSe)[/\\]urn.*[.]ttcn)|(.*[/\\]IMS[/\\]XCAP_XSD[/\\].*[.]ttcn)|(.*[/\\]MCX[/\\]CommonXSD[/\\].*[.]ttcn)|(.*[/\\].*[/\\][Cc]ommon[/\\]TestcaseProperties.*[.]ttcn))</ignoredResourceRegExp>   
      <!-- added pattern for files generated from ASN.1 -->
      <ignoredResourceRegExp>((.*asn[.]json[.]ttcn)|(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)|(.*[/\\]Common[/\\](HTTP)[/\\]uri.*[.]ttcn)|(.*[/\\]LTE_A_R12[/\\](D2D_ProSe)[/\\]urn.*[.]ttcn)|(.*[/\\]IMS[/\\]XCAP_XSD[/\\].*[.]ttcn)|(.*[/\\]MCX[/\\]CommonXSD[/\\].*[.]ttcn)|(.*[/\\].*[/\\][Cc]ommon[/\\]TestcaseProperties.*[.]ttcn))</ignoredResourceRegExp>   
      <!--   <settingRecursiveProcessing>true</settingRecursiveProcessing>  -->
      <checkNoUninitializedFieldsInTemplates>false</checkNoUninitializedFieldsInTemplates>
      <checkNoUninitializedFieldsInTemplatesRecursion>false</checkNoUninitializedFieldsInTemplatesRecursion>
@@ -123,6 +124,8 @@
      </namingConventionsConfig>
      <dependencyOutputPath>DOCUMENTATION</dependencyOutputPath>
      <pathFormattedOutputPath>FORMATTED</pathFormattedOutputPath>
      <titanCompilerPath>./compiler</titanCompilerPath>
      <jsonSchemaPath></jsonSchemaPath>
      <!-- formattingParameters>
        <tabs>false</tabs>
        <unixNewline>false</unixNewline>
@@ -145,8 +148,8 @@
    </QualityCheckProfile>
    <QualityCheckProfile>
      <profileName>defaultProfile</profileName>
      <profileVersion>v2.1.0b3</profileVersion>
      <ignoredResourceRegExp>(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <profileVersion>v2.1.0b4</profileVersion>
      <ignoredResourceRegExp>(.*asn[.]json[.]ttcn)|(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <settingAbortOnError>true</settingAbortOnError>
      <loggingConfiguration>
        <showFullPath>false</showFullPath>
@@ -263,11 +266,13 @@
        <enumeratedValueRegExp>e_[a-z].*</enumeratedValueRegExp>
      </namingConventionsConfig>
      <pathFormattedOutputPath>FORMATTED</pathFormattedOutputPath>
      <titanCompilerPath>compiler</titanCompilerPath>      
      <jsonSchemaPath></jsonSchemaPath>
    </QualityCheckProfile>
    <QualityCheckProfile>
      <profileName>nothing</profileName>
      <profileVersion>v2.1.0b3</profileVersion>
      <ignoredResourceRegExp>(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <profileVersion>v2.1.0b4</profileVersion>
      <ignoredResourceRegExp>(.*asn[.]json[.]ttcn)|(.*[/\\]Common[/\\](IMS_LibSip|IMS_XSD)[/\\].*[.]ttcn)</ignoredResourceRegExp>
      <settingAbortOnError>true</settingAbortOnError>
      <loggingConfiguration>
        <showFullPath>false</showFullPath>
@@ -382,6 +387,8 @@
        <enumeratedValueRegExp>e_[a-z].*</enumeratedValueRegExp>
      </namingConventionsConfig>
      <pathFormattedOutputPath>FORMATTED</pathFormattedOutputPath>
      <titanCompilerPath>compiler</titanCompilerPath>
      <jsonSchemaPath></jsonSchemaPath>            
    </QualityCheckProfile>    
  </ConfigurationProfiles>
  <defaultConfigurationProfile>all</defaultConfigurationProfile>
+341 −0
Original line number Diff line number Diff line
package de.ugoe.cs.swe.T3Q;

import java.io.FileReader;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;

import de.ugoe.cs.swe.common.logging.LoggingInterface.LogLevel;

public class JsonSchemaBridge {
	StringBuilder ttcn = new StringBuilder();

	public JsonSchemaBridge() {
	}
	
	public void convertASN1toJSONSchema(String titanCompilerPath, List<String> asnFilePaths, String targetPath) {
		Process process = null;
	    try {
	        List<String> command = new ArrayList<>();
	        command.add(titanCompilerPath);
	        command.add("--ttcn2json");
	        command.addAll(asnFilePaths);
	        command.add("-");
	        command.add(targetPath);
	        ProcessBuilder processBuilder = new ProcessBuilder(command);
	        if (T3Q.getLogLevel() == LogLevel.DEBUG) {
	        	System.out.println("Running Compiler: "+String.join(" ", command));
	        }
	        processBuilder.redirectErrorStream(true);

	        process = processBuilder.start();  // Start process
	        try (InputStream inputStream = process.getInputStream()) {
	            byte[] output = inputStream.readAllBytes();
		        if (T3Q.getLogLevel() == LogLevel.DEBUG) {
		        	System.out.println("Titan Compiler output: \n" + new String(output).replaceAll("\n", "\nTITAN: "));
		        }
	        }

	        int exitCode = process.waitFor();
	        if (exitCode != 0) {
	        	System.err.println("ERROR: Execution problems encountered while converting ASN.1 files to JSON with Titan");
	        }
	    } catch (Exception e) {
        	System.err.println("ERROR: Execution problems encountered while converting ASN.1 files to JSON with Titan: "+e.getLocalizedMessage());
	    } finally {
	        if (process != null) {
	            process.destroy();  // Ensure cleanup in all Java versions
	        }
	    }
	}
	
	
	private void append(String s) {
//		System.out.print(s);
		ttcn.append(s);
	}
	private void log(String s) {
//		System.out.println(s);
	}
	
	
	public void process(String path) throws Exception {
		JsonElement jsonElement = JsonParser.parseReader(new FileReader(path));
//        dumpJson("", jsonElement);
        //TODO: build reference map
		//TODO: break down and process recursively
        log("");
        int definitionsCount = 0;
        for (var d : jsonElement.getAsJsonObject().get("definitions").getAsJsonObject().entrySet()) {
        	//module
        	log(d.getKey());
        	//TODO: split across files?
        	append("module "+d.getKey()+" {\n"); 
            for (var e : d.getValue().getAsJsonObject().entrySet()) {
            	//type / object
            	log("  "+e.getKey());
            	//TODO: check for others?
            	processObject(e.getKey(), e.getValue().getAsJsonObject(), "  ", false);
            	append("\n\n");
            	definitionsCount++;
            	
            }
        	append("}\n\n");
        }
//        log(ttcn);
//        System.out.println(ttcn);
        Files.writeString(Path.of(path+".ttcn"), ttcn, 
        		StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
        if (T3Q.getLogLevel() == LogLevel.DEBUG) {
        	System.out.println("Converted "+definitionsCount+" definitions");
        }
	}
	
	private boolean isOptional(JsonObject o) {
		if (o.get("anyOf")!=null) {
			if (o.get("anyOf").getAsJsonArray().get(0).getAsJsonObject().get("type").getAsString().equals("null")) {
//				append(" optional ");
				return true;
			}			
		}
		return false;
	}
	
	private void processObject(String name, JsonObject o, String prefix, boolean skipBraces) {
		//TODO: check for nulls
		//TODO: extract keys
		//TODO: handle different types
		//TODO: handle unions
		if (o.get("anyOf")!=null) {
			processAnyOf(name, o, prefix);
		} else if (o.get("enum")!=null) {
			processEnum(name, o, prefix);
		} else if (o.get("$ref")!=null) {
			processRef(name, o, prefix);
		} else {
			var type = o.get("type").getAsString();
			if (type.equals("object")) {
				processStructured(name, o, prefix, skipBraces);
			} else if (type.equals("array")) {
				processArray(name, o, prefix);
			} else if (type.equals("null")) {
				//optional alternative?
    			log(prefix+"  OPTIONAL?");
    			append("anytype ");
			} else if (o.get("type").isJsonPrimitive()) {
				processPrimitive(name, o, prefix, type);
			} else {
				System.err.println(prefix+"  UNSUPPORTED TYPE: "+type);
			}
		}
	}

	private void processPrimitive(String name, JsonObject o, String prefix, String type) {
		//primitives: handle
		var subType = o.get("subType");
		log(prefix+"  PRIMITIVE: "+type);
		if (subType==null) {
			subType = new JsonPrimitive(type);
		}
		preamble(name, prefix, subType);
		//TODO: clean up
		//custom:
//		append(prefix);
//		if (name!=null) {
//			append("type ");
//		}
//		if (subType!=null) {
//			append(subType.getAsString()+" ");
//		} else {
//			append(prefix+type+" ");
//		}
//		if (name!=null) {
//			append(name+" ");
//		}
		if (name!=null) {
//			append("\n");
		}
	}

	private void processArray(String name, JsonObject o, String prefix) {
		//array
		//TODO: handle
		var subType = o.get("subType");
		var itemType = o.get("items").getAsJsonObject();
		
//				preamble(name, prefix, subType);
		//custom handling
		append(prefix);
		if (name!=null) {
			append("type ");
		}
		if (subType!=null) {
			append(subType.getAsString()+" ");
		}
		processObject(null, itemType, prefix, false);
		if (name!=null) {
			append(name+" ");
		}
//				append("{\n";
		append("");
//				append("\n"+prefix+"}\n";
	}

	private void processStructured(String name, JsonObject o, String prefix, boolean skipBraces) {
		//fields
		var subType = o.get("subType");
		log(prefix+"->[object:"+subType+"]");
		preamble(name, prefix, subType);
		if (!skipBraces) {
			append("{\n");
		}
		JsonObject props = o.get("properties").getAsJsonObject();
		var pi = 1;
		for (var p : props.entrySet()) {
			log(prefix+"  "+p.getKey());
			JsonObject pDescription = p.getValue().getAsJsonObject();
			append(prefix+"  ");
			processObject(null, pDescription, prefix+"  ", false);
			var opt ="";
			if (isOptional(pDescription)) {
				opt = " optional";
			}
			append(p.getKey()+opt);
			if (pi < props.entrySet().size()) {
				append(",");
				append("\n");
			}
			pi++;
		}
//				ttcn = ttcn.substring(0, ttcn.length()-3);
		if (!skipBraces) {
			append("\n"+prefix+"} ");
		}
		o.get("required");
	}

	private void processRef(String name, JsonObject o, String prefix) {
		var refName = Arrays.asList(o.get("$ref").getAsString().split("/")).getLast();
		if (refName.startsWith("_")) {
			refName = refName.substring(1);
		}
		//TODO: conflicts?
		log(prefix+"->[ref] "+refName+" : "+o.get("$ref").getAsString());
		//TODO: some weird references generated by titan...
//			preamble(name, prefix, null);
		if (name!=null) {
			append(prefix);
			append("type ");
		}
		append(refName+" ");
		if (name!=null) {
			append(name+" ");
		}
		if (name!=null) {
//			append("\n");
		}
	}

	private void processEnum(String name, JsonObject o, String prefix) {
		//TODO: handle enums
		log(prefix+"->[enum]");
		for (var en : o.get("enum").getAsJsonArray()) {
			log(prefix+"  "+en.getAsString());
		}
		//TODO: handle numeric values
		preamble(name, prefix, new JsonPrimitive("enumerated"));
		if (name==null) {
			append("{\n"+prefix+"  ");
		} else {
			append("{\n"+prefix+"  ");
		}
		var ei = 1;
		JsonArray enums = o.get("enum").getAsJsonArray();
		for (var en : enums) {
			append(en.getAsString());
			if (ei < enums.size()) {
				append(", ");
			}
			ei++;
		}
		if (name==null) {
			append("\n"+prefix+"} ");
		} else {
			append("\n"+prefix+"} ");
		}
	}

	private void processAnyOf(String name, JsonObject o, String prefix) {
		log(prefix+"->[union]");
		if (isOptional(o)) {
			var opt = o.get("anyOf").getAsJsonArray().get(1).getAsJsonObject();
			processObject(null, opt, prefix+"  ", false);
		} else {
			preamble(name, prefix, new JsonPrimitive("union"));
			
			append("{\n");
			var ui = 1;
			JsonArray uItems = o.get("anyOf").getAsJsonArray();
			for (var u : uItems) {
				JsonObject uo = u.getAsJsonObject();
				//fix formatting
				processObject(null, uo, prefix+"  ", true);
				if (ui < uItems.size()) {
					append(",");
					append("\n");
				}
				ui++;
			}
			append("\n");
			if (name!=null) {
				append(prefix+"} ");
//				append("\n");
			} else {
				append(prefix+"  } ");
			}
		}
	}

	private void preamble(String name, String prefix, JsonElement subType) {
		if (name!=null) {
			append(prefix);
			append("type ");
		}
		if (subType!=null) {
			append(subType.getAsString()+" ");
		}
		if (name!=null) {
			append(name+" ");
		}
	}

    //for reference and debugging
	private void dumpJson(String prefix, Map.Entry<String,JsonElement> e) {
	    log("");
	    System.out.print(prefix+"  "+e.getKey() + ":");
	    dumpJson(prefix + "  ", e.getValue());
	}
	
	//for reference and debugging
	private void dumpJson(String prefix, JsonElement e) {
	    if (e.isJsonArray()) {
	        ((JsonArray) e).forEach(a -> dumpJson(prefix + "  ", a));
	    } else if (e.isJsonObject()) {
	        ((JsonObject) e).entrySet().forEach(a -> dumpJson(prefix + "  ", a));
	    } else if (e.isJsonPrimitive()) {
	        System.out.print("  "+e);
	    }
	}

}
+132 −11
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -17,6 +18,9 @@ import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;

import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
@@ -32,7 +36,7 @@ import de.ugoe.cs.swe.scoping.TTCN3GlobalScopeProvider;

public class T3Q {
	//TODO: externalise meta-data
	private static String versionNumber = "v2.1.0b3";
	private static String versionNumber = "v2.1.0b4";
	private static String supportedTTCN3Version = "4.10.1";
	// set during automated server builds -> no longer displayed or used..
	private static String buildStamp = "---BUILD_STAMP---";
@@ -45,8 +49,12 @@ public class T3Q {
	private String destinationPath = null;
	private boolean generateNewConfiguration = false;
	private boolean generateLocalDependencies = false;
	private boolean convertJSONSchemas = false;
	private boolean convertASN1toJSONSchema = false;
	private final Stopwatch stopwatch = Stopwatch.createUnstarted();
	private boolean analyzeUsage = false;
	//TODO: expose in configuration?
	private String schemaFile = "asn.json";

	// private boolean formattingEnabled = false;

@@ -107,6 +115,15 @@ public class T3Q {
			System.out.println("ERRORING OUT!");
		}

		if (this.isConvertASN1toJSONSchema()) {
			//TODO: skip if none!
			convertASN1toJSONSchema();
		}

		if (this.isConvertJSONSchemas()) {
			convertJSONSchemas();
		}
		
		LoggingInterface logger = new LoggingInterface(activeProfile.getLoggingConfiguration());
		logger.setMaximumLogLevel(logLevel);
		TTCN3ResourceProvider resourceProvider = new TTCN3ResourceProvider(inputPaths, logger, activeProfile, runtime);
@@ -131,11 +148,94 @@ public class T3Q {
				+ MiscTools.msToString(stopwatch.elapsed(TimeUnit.MILLISECONDS)) + " minutes." + '\n');			
	}

	private void convertASN1toJSONSchema() {
		List<String> asn1Paths = new ArrayList<>();
		for (String path : inputPaths) {
			File file = new File(path);
			if (file.isFile() && file.getName().endsWith(".asn")) {
				asn1Paths.add(file.getAbsolutePath());
			} else if (file.isDirectory()) {
				Collection<File> files = FileUtils.listFiles(file,
					new RegexFileFilter("^.*asn$"),
					DirectoryFileFilter.DIRECTORY);
				for (File f : files) {
					asn1Paths.add(f.getAbsolutePath());
				}
			}
		}
		//TODO: spaces and special characters in paths?
		JsonSchemaBridge bridge = new JsonSchemaBridge();
		if (!asn1Paths.isEmpty()) {
			stopwatch.start();
			System.out.println("Converting "+asn1Paths+" ASN.1 files to JSON Schema...");
			bridge.convertASN1toJSONSchema(activeProfile.getTitanCompilerPath(), asn1Paths, activeProfile.getJsonSchemaPath()+schemaFile);
			System.out.println("Converted "+asn1Paths+" ASN.1 files to JSON Schema in "+MiscTools.msToString(stopwatch.elapsed(TimeUnit.MILLISECONDS)) + " minutes." + '\n');
			stopwatch.stop();

			inputPaths.add(activeProfile.getJsonSchemaPath()+schemaFile);
		}
		//TODO: clean-up?
	}
	private void convertJSONSchemas() {
		JsonSchemaBridge bridge = new JsonSchemaBridge();
		//TODO: handle other schemas? -> need to add result in input files..
		ArrayList<String> processedSchemas = new ArrayList<>();
		for (String path : inputPaths) {
			File file = new File(path);
			if (file.isFile()) {
				try {
        			if (file.isFile() && file.getName().endsWith(schemaFile)) {
        				stopwatch.start();
        				bridge.process(file.getAbsolutePath());
        				System.out.println("Converted JSON Schema "+file.getAbsolutePath()+" to TTCN-3 in "+MiscTools.msToString(stopwatch.elapsed(TimeUnit.MILLISECONDS)) + " minutes." + '\n');
        				stopwatch.stop();
        				
        				processedSchemas.add(path);
        			}
				} catch (Exception e) {
					logException(e);
				}
			} else if (file.isDirectory()) {
				Collection<File> files = FileUtils.listFiles(file,
					new RegexFileFilter("^.*"+schemaFile+"$"),
					DirectoryFileFilter.DIRECTORY);
				for (File f : files) {
					try {
        				stopwatch.start();
						bridge.process(f.getAbsolutePath());
        				System.out.println("Converted JSON Schema "+file.getAbsolutePath()+" to TTCN-3 in "+MiscTools.msToString(stopwatch.elapsed(TimeUnit.MILLISECONDS)) + " minutes." + '\n');
        				stopwatch.stop();

        				processedSchemas.add(f.getAbsolutePath());
					} catch (Exception e) {
						logException(e);
					}
				}
			}
		}
		for (String s : processedSchemas) {
			if (inputPaths.contains(s)) {
				inputPaths.remove(s);
			}
			inputPaths.add(s+".ttcn");
		}
		//TODO: Double check above covers everything
//		if (inputPaths.contains(schemaFile)) {
//			inputPaths.remove(schemaFile);
//			inputPaths.add(schemaFile+".ttcn");
//		}
	}

	public static void main(String[] args) {
		try {
			T3Q tool = new T3Q();
			tool.run(args);
		} catch (Exception e) {
			logException(e);
		}
	}

	private static void logException(Exception e) {
		if (getLogLevel() == LogLevel.DEBUG) {
			e.printStackTrace();
		} else {
@@ -147,7 +247,6 @@ public class T3Q {
					+ stacktrace + "\n  Run T3Q with --verbosity=DEBUG for a more detailed report");
		}
	}
	}

	private boolean handleCommandLineArguments(String[] args) throws TerminationException {
		// parseCommandLineArguments(args);
@@ -215,6 +314,12 @@ public class T3Q {
		if (commandLine.hasOption("analyze-usage")) {
			this.setAnalyzeUsage(true);
		}
		if (commandLine.hasOption("convert-asn1-to-schema")) {
			this.setConvertASN1toJSONSchema(true);
		}
		if (commandLine.hasOption("convert-schemas")) {
			this.setConvertJSONSchemas(true);
		}
		if (commandLine.hasOption("verbosity")) {
			this.selectLogLevel(commandLine.getOptionValue("verbosity"));
		}
@@ -450,4 +555,20 @@ public class T3Q {
		this.analyzeUsage = analyzeUsage;
	}

	public boolean isConvertJSONSchemas() {
		return convertJSONSchemas;
	}

	public void setConvertJSONSchemas(boolean convertJSONSchemas) {
		this.convertJSONSchemas = convertJSONSchemas;
	}

	public boolean isConvertASN1toJSONSchema() {
		return convertASN1toJSONSchema;
	}

	public void setConvertASN1toJSONSchema(boolean convertASN1toJSONSchema) {
		this.convertASN1toJSONSchema = convertASN1toJSONSchema;
	}

}
+5 −2
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import de.ugoe.cs.swe.tTCN3.TTCN3Module;
import de.ugoe.cs.swe.validation.TTCN3StatisticsProvider;

public class TTCN3ResourceProvider {
	private static final String extensionPattern = "^.*ttcn3$|^.*ttcn$|^.*3mp$";
	private ArrayList<String> paths;
	private LoggingInterface logger;
	private QualityCheckProfile activeProfile;
@@ -89,10 +90,12 @@ public class TTCN3ResourceProvider {
			File file = new File(path);
						
			if (file.isFile()) {
				if (file.getName().matches(extensionPattern)) {
					parser.add(new FileParser(file, qualifiedNameProvider, logger));
				}
			} else if (file.isDirectory()) {
				Collection<File> files = FileUtils.listFiles(file,
						new RegexFileFilter("^.*ttcn3$|^.*ttcn$|^.*3mp$"),
						new RegexFileFilter(extensionPattern),
						DirectoryFileFilter.DIRECTORY);
				for (File f : files) {
					parser.add(new FileParser(f, qualifiedNameProvider, logger));
Loading