/*-
 * ~~~~~~licensing~~~~~~
 * core-support-design
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.platform.core.support.design.openapi;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.json.Json;
import javax.json.stream.JsonGenerator;

import org.apache.commons.io.FileUtils;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.Generator;
import org.openapitools.codegen.config.CodegenConfigurator;
import org.openapitools.codegen.config.CodegenConfiguratorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.serialization.JavaParserJsonSerializer;
import com.github.javaparser.utils.SourceRoot;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import javassist.CtClass;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.support.design.classgen.Cu2JaConverter;
import ru.entaxy.platform.core.support.design.openapi.utils.CompilerRequestor;
import ru.entaxy.platform.core.support.design.openapi.utils.INameEnvironmentImpl;

public class EntaxyOpenApiGenerator {

	private static final Logger log = LoggerFactory.getLogger(EntaxyOpenApiGenerator.class);
	
	public enum GENERATION_STATUS {
		NONE,
		IN_PROGRESS,
		OK,
		FAILED
	}
	
	public enum GENERATION_PHASE {
		NONE,
		CHECK,
		GENERATE_JAVA,
		PARSE_JAVA,
		GENERATE_CLASSES
	} 

	public enum GENERATION_PHASE_STATE {
		PRE_EXECUTE,
		IN_PROGRESS,
		DONE
	} 
	
	public static interface GenerationCallback {
		
		public void event(GenerationResult generationResult);
		
	}
	
	public static abstract class AbstractResult {
		public GENERATION_STATUS status = GENERATION_STATUS.NONE;
		public List<Throwable> exceptions = new ArrayList<>();;
		public Map<String, Object> properties = new HashMap<>();
		
		public AbstractResult status(GENERATION_STATUS newStatus) {
			this.status = newStatus;
			return this;
		}

		public boolean isOk() {
			return GENERATION_STATUS.OK.equals(status);
		}

		public boolean isFailed() {
			return GENERATION_STATUS.FAILED.equals(status);
		}
		
		public boolean isInProgress() {
			return GENERATION_STATUS.IN_PROGRESS.equals(status);
		}
				
		public boolean isFinished() {
			return isOk() || isFailed();
		}
	}
	
	public static class GenerationResult extends AbstractResult {
		
		public GENERATION_PHASE currentPhase = GENERATION_PHASE.NONE;
		public Map<GENERATION_PHASE, PhaseResult> phases =  new LinkedHashMap<>();
		
		public EntaxyOpenApiGenerator generator;
		
		public GenerationResult phase(GENERATION_PHASE phase) {
			return this.phase(phase, new PhaseResult());
		}

		public GenerationResult phase(GENERATION_PHASE phase, PhaseResult phaseResult) {
			phases.put(phase, phaseResult);
			currentPhase = phase;
			return this;
		}
		
		public GenerationResult phaseStatus(GENERATION_STATUS newStatus) {
			this.currentPhaseResult().status = newStatus;
			this.generator.callback(this);
			return this;
		}
		
		public GenerationResult phaseInProgress() {
			this.currentPhaseResult().state(GENERATION_PHASE_STATE.IN_PROGRESS);
			return this.phaseStatus(GENERATION_STATUS.IN_PROGRESS);
		}

		public GenerationResult phaseOk() {
			this.currentPhaseResult().state(GENERATION_PHASE_STATE.DONE);
			return this.phaseStatus(GENERATION_STATUS.OK);
		}
		
		public GenerationResult phaseFailed() {
			this.currentPhaseResult().state(GENERATION_PHASE_STATE.DONE);
			return this.phaseStatus(GENERATION_STATUS.FAILED);
		}
			
		public PhaseResult currentPhaseResult() {
			return this.phases.get(currentPhase);
		}
		
		public boolean isCurrentPhaseOk() {
			return (currentPhase!=null)
				&& currentPhaseResult().status.equals(GENERATION_STATUS.OK);
		}
		
	}

	public static class PhaseResult extends AbstractResult  {
		public List<Object> resultObjects = new ArrayList<>();
		public GENERATION_PHASE_STATE currentState = GENERATION_PHASE_STATE.PRE_EXECUTE;
		public PhaseResult state(GENERATION_PHASE_STATE state) {
			this.currentState = state;
			return this;
		}
	}
	
	protected static abstract class PhaseProcessor {
		
		protected EntaxyOpenApiGenerator generator; 
		protected GenerationResult generationResult;
		
		public void process(EntaxyOpenApiGenerator generator, GenerationResult generationResult) {
			this.generator = generator;
			this.generationResult = generationResult;
			this.generationResult.phase(getPhase());
			this.generator.callback(this.generationResult);
			execute();
		}
		
		protected abstract GENERATION_PHASE getPhase();
		
		protected void execute() {
			this.generationResult.currentPhaseResult().state(GENERATION_PHASE_STATE.IN_PROGRESS);
			this.generator.callback(this.generationResult);
			doExecute();
			this.generationResult.currentPhaseResult().state(GENERATION_PHASE_STATE.DONE);
			this.generator.callback(this.generationResult);
		};
		
		protected abstract void doExecute();
		
		protected void failWithException(Throwable e) {
			generationResult.exceptions.add(e);
			generationResult.currentPhaseResult().exceptions.add(e);
			generationResult.currentPhaseResult().state(GENERATION_PHASE_STATE.DONE);
			generationResult.phaseFailed();
			generator.callback(generationResult);
		}
	} 
	
	protected static class CheckPhaseProcessor extends PhaseProcessor {

		public CheckPhaseProcessor() {
			super();
		}
		
		@Override
		protected GENERATION_PHASE getPhase() {
			return GENERATION_PHASE.CHECK;
		}

		@Override
		protected void doExecute() {
			this.generationResult.currentPhaseResult().status(GENERATION_STATUS.IN_PROGRESS);
			SwaggerParseResult result = (new OpenAPIV3Parser()).readLocation(
					this.generator.getUrl()
					, null
					, null);
			OpenAPI api = result.getOpenAPI();
			if (api != null) {
				this.generationResult.currentPhaseResult().properties.put("api", api);
				this.generationResult.properties.put("api", api);
				this.generationResult.currentPhaseResult().status(GENERATION_STATUS.OK);
			} else {
				this.generationResult.currentPhaseResult().status(GENERATION_STATUS.FAILED);
			}
		}
		
	}
	
	protected static class GenerateJavaPhaseProcessor extends PhaseProcessor {

		public GenerateJavaPhaseProcessor() {
			super();
		}
		
		@Override
		protected GENERATION_PHASE getPhase() {
			return GENERATION_PHASE.GENERATE_JAVA;
		}

		@Override
		protected void doExecute() {
			this.generationResult.generator.initializeRootFolder();
			this.generationResult.phaseInProgress();
			
			CodegenConfigurator configurator = new CodegenConfigurator();
			Generator codeGenerator;
			
			if (!CommonUtils.isValid(generator.getApiPackage())) {
				generator.setApiPackage("entaxy.openapi." 
					+ generator.apiTitleConverted 
					+ ".v_" + generator.apiVersionConverted);
			}
			if (!CommonUtils.isValid(generator.getModelPackage())) {
				generator.setModelPackage(generator.apiPackage + ".model");
			}

			applyImportMappingsKvpList(configurator);

			configurator.setApiPackage(generator.apiPackage);
		    configurator.setModelPackage(generator.modelPackage);

		    configurator.setGeneratorName("jaxrs-cxf");

		    configurator.setOutputDir(
		    	Paths.get(generator.targetDir.getAbsolutePath(), "sources")
		    	.toFile()
		    	.getAbsolutePath());

		    configurator.setInputSpec(generator.getUrl());
			HashMap<String, Object> additionalProperties = new HashMap<>();
			additionalProperties.put("useTags", false);
			configurator.setAdditionalProperties(additionalProperties);

	        try {

	            final ClientOptInput clientOptInput = configurator.toClientOptInput();

	            codeGenerator = new DefaultGenerator(false);

	            codeGenerator.opts(clientOptInput);
	            codeGenerator.generate();

	            generationResult.properties.put("generator.java.source.path", "sources/src/gen/java");

	            generationResult.phaseOk();

	        } catch (Exception e) {

	        	log.error("openapi-generator finished with exception", e);
	        	failWithException(e);
	        }

		}

		private void applyImportMappingsKvpList(CodegenConfigurator configurator) {
			OpenAPI api = (OpenAPI)this.generationResult.properties.get("api");
			List<String> list = new ArrayList<>();
			if (api.getComponents() != null) {
				for (String schemaName : api.getComponents().getSchemas().keySet()) {
					list.add(schemaName + "=" + generator.modelPackage + "." + schemaName);
				}
				CodegenConfiguratorUtils.applyImportMappingsKvpList(list, configurator);
			}
		}

	}
	
	protected static class ParseJavaPhaseProcessor extends PhaseProcessor {
		
		public ParseJavaPhaseProcessor() {
			super();
		}
		
		@Override
		protected GENERATION_PHASE getPhase() {
			return GENERATION_PHASE.PARSE_JAVA;
		}
		
		@Override
		protected void doExecute() {

			List<CompilationUnit> apiCUs;
			List<CompilationUnit> modelCUs;
			
			String sourceRootFolder = Paths.get( generator.targetDir.getAbsolutePath() 
					,generationResult.properties.get("generator.java.source.path")
						.toString()).toAbsolutePath().toString();
			
			String apiPackageFolder = generator.apiPackage.replace('.', '/');
			String modelPackageFolder = generator.modelPackage.replace('.', '/');
			
			String apiFolder = Paths.get(sourceRootFolder, apiPackageFolder).toAbsolutePath().toString();
			String modelFolder = Paths.get(sourceRootFolder, modelPackageFolder).toAbsolutePath().toString();
			
			File apiFolderFile = new File(apiFolder);
			File[] apis = apiFolderFile.listFiles((dir, name)->dir.getAbsolutePath().equals(apiFolderFile.getAbsolutePath()) && name.endsWith(".java"));
			File modelFolderFile = new File(modelFolder);
			File[] models = modelFolderFile.listFiles((dir, name)->dir.getAbsolutePath().equals(modelFolderFile.getAbsolutePath()) && name.endsWith(".java"));

			String parsedRootFolder = Paths.get(generator.targetDir.getAbsolutePath(), "parsed").toAbsolutePath().toString();
			try {
				Files.createDirectories(Paths.get(parsedRootFolder));
				Files.createDirectories(Paths.get(parsedRootFolder, "model"));
			} catch (IOException e) {
				log.error("Error creating directories", e);
			}
			
			SourceRoot sourceRoot = new SourceRoot(Paths.get(sourceRootFolder));
			
			JavaParserJsonSerializer serializer = new JavaParserJsonSerializer();
			
			apiCUs = new ArrayList<>();
			modelCUs = new ArrayList<>();
			
			for (int i=0; i<apis.length; i++) {
				String targetPath = Paths.get(parsedRootFolder, apis[i].getName()+".json").toAbsolutePath().toString();
				try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
					CompilationUnit cu = sourceRoot.parse(generator.apiPackage, apis[i].getName());
				
					apiCUs.add(cu);
					
					JsonGenerator generator = Json.createGeneratorFactory(null).createGenerator(bos);

					serializer.serialize(cu, generator);
				
					Files.write(Paths.get(targetPath), bos.toByteArray(), StandardOpenOption.CREATE);
				} catch (IOException e) {
					log.error("javaparser finished with exception", e);
					failWithException(e);
					return;
				}
			}
			
			if (models!=null && models.length>0) {
				for (int i=0; i<models.length; i++) {
					String targetPath = Paths.get(parsedRootFolder, "model", models[i].getName()+".json").toAbsolutePath().toString();
					try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
						CompilationUnit cu = sourceRoot.parse(generator.modelPackage, models[i].getName());
					
						modelCUs.add(cu);
						
						JsonGenerator generator = Json.createGeneratorFactory(null).createGenerator(bos);
	
						serializer.serialize(cu, generator);
					
						Files.write(Paths.get(targetPath), bos.toByteArray(), StandardOpenOption.CREATE);
					} catch (IOException e) {
						log.error("javaparser finished with exception", e);
						failWithException(e);
						return;
					}
				}	
				generationResult.properties.put("parser.cu.model", modelCUs);
			}
			
			generationResult.properties.put("parser.java.path", parsedRootFolder);
			generationResult.properties.put("parser.cu.api", apiCUs);
            
            generationResult.phaseOk();		
		}
		
	}
	
	protected static class GenerateClassesPhaseProcessor extends PhaseProcessor {
		
		public GenerateClassesPhaseProcessor() {
			super();
		}
		
		@Override
		protected GENERATION_PHASE getPhase() {
			return GENERATION_PHASE.GENERATE_CLASSES;
		}
		
		@Override
		protected void doExecute() {
			try {
				String genRootFolder = Paths.get(generator.targetDir.getAbsolutePath(), "sources", "src", "gen", "java").toString();
				String classesRootFolder = Paths.get(generator.targetDir.getAbsolutePath(), "classes").toString();
				try (Stream<Path> stream = Files.walk(Paths.get(genRootFolder))) {
					List<ICompilationUnit> list = stream.filter(f -> Files.isRegularFile(f) && f.toString().endsWith(".java"))
		                    .map(f -> ru.entaxy.platform.core.support.design.openapi.utils.CompilationUnit.build(f.toAbsolutePath(), genRootFolder))
		                    .filter(Objects::nonNull)
		                    .collect(Collectors.toList());
		            ICompilationUnit[] units = list.toArray(new ICompilationUnit[]{});
		            compileApiSource(units, classesRootFolder);
		            
		            
		            String apiPackageFolder = generator.apiPackage.replace(".", System.getProperty("file.separator"));
					String modelPackageFolder = generator.modelPackage.replace(".", System.getProperty("file.separator"));
		            List<String> apiClassesFinal = getFileNamesInFolder(generator.apiPackage, 
		            		classesRootFolder + System.getProperty("file.separator") + apiPackageFolder);
		            List<String> modelClassesFinal = getFileNamesInFolder(generator.modelPackage, 
		            		classesRootFolder + System.getProperty("file.separator") + modelPackageFolder);
					
					generationResult.properties.put("classes.path", classesRootFolder);
					generationResult.properties.put("classes.api", apiClassesFinal);
					generationResult.properties.put("classes.model", modelClassesFinal);
		            
					log.debug(">>>API compilation completed");
					
		        } catch (IOException e) {
		            throw e;
		        }
				
	            generationResult.phaseOk();	
			
			} catch (Exception e) {
				log.error("javassist finished with exception", e);
				failWithException(e);
				return;			
			}
			
		}
		
		private void compileApiSource(ICompilationUnit[] sources, String classesRootFolder) {
	        IErrorHandlingPolicy passAll = DefaultErrorHandlingPolicies.proceedWithAllProblems();
	        Map<String, String> options = new HashMap<>();
	        options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
	        options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_11);
	        options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_11);
	        options.put(CompilerOptions.OPTION_Encoding, "UTF-8");
	        CompilerOptions compilerOptions = new CompilerOptions();
	        compilerOptions.set(options);
	        compilerOptions.parseLiteralExpressionsAsConstants = true;
	        CompilerRequestor requestor = new CompilerRequestor(classesRootFolder);
	        DefaultProblemFactory problemFactory = new DefaultProblemFactory();
	        ClassLoader cl = EntaxyOpenApiGenerator.class.getClassLoader();
	        Compiler compiler = new Compiler(new INameEnvironmentImpl(cl), passAll, compilerOptions,
	                requestor, problemFactory);
	        compiler.compile(sources);
	    }
		
		private List<String> getFileNamesInFolder(String packageName, String path) {
	    	List<String> filesList = new ArrayList<>();
	    	File[] files = new File(path).listFiles();
			if (files == null ) return filesList;
	    	for (File file : files) {
	    	    if (file.isFile()) {
	    	    	filesList.add(packageName + "."
	    	    			+ file.getName().substring(0, file.getName().lastIndexOf(".")));
	    	    }
	    	}
	    	return filesList;
	    }
	}
	
	@Deprecated(since = "1.10", forRemoval = true)
	protected static class GenerateClassesPhaseProcessorDeprecated extends PhaseProcessor {
		
		public GenerateClassesPhaseProcessorDeprecated() {
			super();
		}
		
		@Override
		protected GENERATION_PHASE getPhase() {
			return GENERATION_PHASE.GENERATE_CLASSES;
		}
		
		@Override
		protected void doExecute() {

			@SuppressWarnings("unchecked")
			List<CompilationUnit> apiCUs = (List<CompilationUnit>)generationResult.properties
					.getOrDefault("parser.cu.api", Collections.emptyList());
			@SuppressWarnings("unchecked")
			List<CompilationUnit> modelCUs = (List<CompilationUnit>)generationResult.properties
					.getOrDefault("parser.cu.model", Collections.emptyList());
			
			try {
				String classesRootFolder = Paths.get(generator.targetDir.getAbsolutePath(), "classes").toString();
				
				Files.createDirectories(Paths.get(classesRootFolder));
	
				Cu2JaConverter converter = new Cu2JaConverter();
				
				List<String> modelClassesImports = new ArrayList<>();
				for (CompilationUnit cu: modelCUs)
					modelClassesImports.add(cu.getPackageDeclaration().get().getName().asString()
							+ "." + cu.getPrimaryType().get().getNameAsString());
				
				List<CtClass> modelClasses = new ArrayList<>();
				List<CtClass> apiClasses = new ArrayList<>();
				
				for (CompilationUnit cu: modelCUs) {
					converter.clearImports();
					for (String s: modelClassesImports)
						converter.addImport(s);
					modelClasses.add(converter.convert(cu));
				}
				
				for (CompilationUnit cu: apiCUs) {
					converter.clearImports();
					for (String s: modelClassesImports)
						converter.addImport(s);
					apiClasses.add(converter.convert(cu));
				}
				
				List<String> apiClassesFinal = new ArrayList<>();
				List<String> modelClassesFinal = new ArrayList<>();
				
				for (CtClass ctClass: modelClasses) {
					if (ctClass == null)
						continue;
					ctClass.writeFile(classesRootFolder);
					modelClassesFinal.add(ctClass.getName());
				}
	
				for (CtClass ctClass: apiClasses) {
					if (ctClass == null)
						continue;
					ctClass.writeFile(classesRootFolder);
					apiClassesFinal.add(ctClass.getName());
				}

				generationResult.properties.put("classes.path", classesRootFolder);
				generationResult.properties.put("classes.api", apiClassesFinal);
				generationResult.properties.put("classes.model", modelClassesFinal);
	            
	            generationResult.phaseOk();		
				
				
			} catch (Exception e) {
				log.error("javassist finished with exception", e);
				failWithException(e);
				return;			
			}
			
		}
	}
	
	protected static Map<GENERATION_PHASE, Class<? extends PhaseProcessor>> processorMap = new HashMap<>();
	
	protected static List<GENERATION_PHASE> defaultPlan = new LinkedList<>();
	
	static {
		
		processorMap.put(GENERATION_PHASE.CHECK, CheckPhaseProcessor.class);
		processorMap.put(GENERATION_PHASE.GENERATE_JAVA, GenerateJavaPhaseProcessor.class);
		processorMap.put(GENERATION_PHASE.PARSE_JAVA, ParseJavaPhaseProcessor.class);
		processorMap.put(GENERATION_PHASE.GENERATE_CLASSES, GenerateClassesPhaseProcessor.class);
		
		defaultPlan.add(GENERATION_PHASE.CHECK);
		defaultPlan.add(GENERATION_PHASE.GENERATE_JAVA);
//		defaultPlan.add(GENERATION_PHASE.PARSE_JAVA);
		defaultPlan.add(GENERATION_PHASE.GENERATE_CLASSES);
		
	}
	
	
	
	protected String url;

	protected String rootFolder = UUID.randomUUID().toString();
	
	protected SwaggerParseResult parseResult;
	
	protected String apiTitleConverted = "unknown_api";
	protected String apiVersionConverted = "1_0_0";
	
	protected String apiPackage;
	protected String modelPackage;
	
	protected List<GENERATION_PHASE> executionPlan = defaultPlan;
	
	protected GenerationCallback callback;
	
	protected GenerationResult result = new GenerationResult();
	
	protected File targetDir = null;
	
	public GenerationResult generate() {
		
		result.generator = this;
		
		result.phase(GENERATION_PHASE.NONE).status(GENERATION_STATUS.NONE);
		callback(result);
		if (executionPlan != null) {
			result.status(GENERATION_STATUS.IN_PROGRESS);
			callback(result);
			for (GENERATION_PHASE phase: executionPlan) {
				PhaseProcessor processor = null;
				try {
					processor = processorMap.get(phase).getConstructor().newInstance();
				} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
						| InvocationTargetException | NoSuchMethodException | SecurityException e) {
					result.currentPhaseResult().exceptions.add(e);
					result.exceptions.add(e);
					result.status(GENERATION_STATUS.FAILED);
					callback(result);
					return result;
				}
				processor.process(this, result);
				if (result.currentPhaseResult().status.equals(GENERATION_STATUS.FAILED))
					return result;
			}
			result.status(GENERATION_STATUS.OK);
			callback(result);
		}
		return result;
	}
	
	protected void initializeRootFolder() {
		if (this.targetDir != null)
			return;
		Path target = Paths.get(
				System.getProperty("karaf.home")
				, "temp"
				, rootFolder);
		this.targetDir = target.toFile();
		if (!this.targetDir.exists())
			this.targetDir.mkdirs();
	}
	
	public void clean() {
		try {
			if (this.targetDir != null)
				FileUtils.deleteDirectory(targetDir);

		} catch (IOException e) {
			log.error("Failed deleting [" + targetDir.getAbsolutePath() + "]", e);
		}
	}
	
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getRootFolder() {
		return rootFolder;
	}

	public void setRootFolder(String rootFolder) {
		this.rootFolder = rootFolder;
	}

	public SwaggerParseResult getParseResult() {
		return parseResult;
	}

	public GenerationCallback getCallback() {
		return callback;
	}

	public void setCallback(GenerationCallback callback) {
		this.callback = callback;
	}
	
	public void callback(GenerationResult generationResult) {
		if (callback != null)
			callback.event(generationResult);
	}

	public List<GENERATION_PHASE> getExecutionPlan() {
		return executionPlan;
	}

	public void setExecutionPlan(List<GENERATION_PHASE> executionPlan) {
		this.executionPlan = executionPlan;
	}

	public String getApiTitleConverted() {
		return apiTitleConverted;
	}

	public void setApiTitleConverted(String apiTitleConverted) {
		this.apiTitleConverted = apiTitleConverted;
	}

	public String getApiVersionConverted() {
		return apiVersionConverted;
	}

	public void setApiVersionConverted(String apiVersionConverted) {
		this.apiVersionConverted = apiVersionConverted;
	}

	public String getApiPackage() {
		return apiPackage;
	}

	public void setApiPackage(String apiPackage) {
		this.apiPackage = apiPackage;
	}

	public String getModelPackage() {
		return modelPackage;
	}

	public void setModelPackage(String modelPackage) {
		this.modelPackage = modelPackage;
	}

	public File getTargetDir() {
		return targetDir;
	}
	
}
