//
// https://www.ramecera.it/myscrewdriver.html
// e-mail: screwdriver@ramecera.it
//
/* This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0 which accompanies this
 * distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html */
package it.ramecera.screwdriver;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import it.ramecera.salad.everyday.Candies;
import it.ramecera.salad.everyday.ExactException;
import it.ramecera.salad.everyday.Mix;
import it.ramecera.salad.everyday.StringInt;
import it.ramecera.salad.everyday.Strings;
import it.ramecera.salad.everyday.Universal;
import it.ramecera.salad.file.Equipment;
import it.ramecera.salad.file.ReadMyFile;
import it.ramecera.salad.graphic.Remember;
import it.ramecera.screwdriver.component.FileComponent;
import it.ramecera.screwdriver.outfits.ClockHands;
import it.ramecera.screwdriver.outfits.ControllerBelong;
import it.ramecera.screwdriver.outfits.Costume;
import it.ramecera.screwdriver.outfits.ELEMethod;
import it.ramecera.screwdriver.outfits.JspBeanElement;
import it.ramecera.screwdriver.outfits.JspKit;
import it.ramecera.screwdriver.outfits.RequestMap;
import it.ramecera.screwdriver.outfits.TableOutfit;
import it.ramecera.screwdriver.utilities.ValidationLabelScrew;
import it.ramecera.screwdriver.utilities.ValidationMessageScrew;

/**
 * <p>
 * Class of characteristic elements of the application to be created.
 * </p>
 * 
 * @author M. Maglioni
 *         <p>
 *         ​​Company: Ramecera™<br>
 *         Creation date: 2020-04-09<br>
 *         Last updated: 2020-09-09<br>
 *         </p>
 *         <p>
 *         History:<br>
 *         The description of N# is in project plan report<br>
 *         2020-09-03 implementation of N3<br>
 *         2020-09-09 implementation of N8<br>
 *         </p>
 */
final public class Skill {

	private static final String sep = System.getProperty(
			"file.separator");
	private static final String SCREW_MAVEN = ".screwMaven";
	// BOOLEAN CHARACTERISTICS
	/** Boolean characteristic */
	public boolean spring = false;
	/** Boolean characteristic */
	public boolean springSecurity = false;
	/** Boolean characteristic */
	public boolean tiles = false;
	/** Boolean characteristic */
	public boolean filter = false;
	/** Boolean characteristic */
	public boolean antiSamy = false;
	/** Boolean characteristic */
	public boolean captcha = false;
	/** Boolean characteristic */
	public boolean ldap = false;
	/** Boolean characteristic */
	public boolean webFlow = false;
	/** Boolean characteristic */
	public boolean internalProperties = false;
	/** Boolean characteristic */
	public boolean pomProperties = false;
	/** Boolean characteristic */
	public boolean mavenBuild = false;
	/** Boolean characteristic */
	public boolean mavenCompiler = false;
	/** Boolean characteristic */
	public boolean mavenCompilerPlugin = false;
	/** Boolean characteristic */
	public boolean mavenWarPlugin = false;
	/** Boolean characteristic */
	public boolean mavenCleanPlugin = false;
	/** Boolean characteristic */
	public boolean springValid = false;
	/** Boolean characteristic */
	public boolean robots = false;
	/** Boolean characteristic */
	public boolean i18n = false;
	/** Boolean characteristic */
	public boolean viewController = false;
	/** Boolean characteristic */
	public boolean defaultAutowire = false;
	/** Boolean characteristic */
	public boolean interceptor = false;
	/** Boolean characteristic */
	public boolean matrixVariables = false;
	/** Boolean characteristic */
	public boolean hibernate = false;
	/** Boolean characteristic */
	public boolean dependencies = false;
	/** Boolean characteristic */
	public boolean jackson;
	/** Boolean characteristic */
	public boolean prettyPrint;
	/** Boolean characteristic */
	public boolean hiberValid;
	/** Boolean characteristic */
	public boolean mimeMapping;
	/** Boolean characteristic */
	public boolean errorPage;
	/** Boolean characteristic */
	public boolean indexJsp;
	/** Boolean characteristic */
	public boolean hasJsp;
	/** Boolean characteristic */
	public boolean hasForm;
	/** Boolean feature, reveals the presence of the "userpass"
	 * markup */
	public boolean hasUseridPassword;
	/** Boolean characteristic */
	/* FUTURE RELEASE N6 */
	// public boolean embedded;
	/** Boolean characteristic */
	public boolean ldapService;
	/** Boolean characteristic */
	public boolean signup;
	/** Boolean characteristic */
	private boolean remember;
	private boolean wellIPermit;

	// SOFTWARE VERSIONS
	/** software version */
	public String applicationServer;
	/** software version */
	public String jeeVersion;
	/** software version */
	public String springVersion;
	/** 1st parameter (macro) of the software version */
	public int springVersion1m;
	/** software version */
	public String tilesVersion;
	/** software version */
	public String mavenCompilerVersion;
	/** software version */
	public String mavenCompilerPluginVersion;
	/** software version */
	public String mavenWarPluginVersion;
	/** software version */
	public String mavenCleanPluginVersion;
	/** software version */
	public String captchaVersion;
	/** software version */
	public String webflowVersion;
	/** software version */
	public String springSecurityReductVersion;
	/** software version */
	public String springSecurityVersion;
	/** software version */
	public String jacksonVersion;
	/** software version */
	public String log4jVers;
	/** software version */
	public String quartzVers;
	/** software version */
	public String hiberValidVersion;
	/** software version */
	public String hibernateVersion;
	/** 1st parameter (macro) of the software version */
	public int hibernateVersion1m;
	/** software version */
	public int jpaVersion;
	/** software version */
	public String hibernateReductVersion;

	// PATHS AND FILES NAMES

	/** path of Java sources */
	public String sorgentiY;
	/** path to Maven main directory */
	public String mainY;
	/** path to Maven's main / java directory */
	public String mainJavaY;
	/** project Eclipse name */
	public String eclipseProjectY;
	/** resource path in webapp */
	public String webAppResourcesY;
	/** webflow path */
	public String webFlowY;
	/** webinf path */
	public String webInfY;
	/** path for utilities for use in java classes */
	public String javaUtilY;
	/** web path for use in java classes */
	public String javaWebY;
	/** web / model path for use in java classes */
	public String javaWebModelY;
	/** web / model / body path for use in java classes, body means the
	 * JSP directory */
	public String javaWebModelBodyY;
	/** web / model / utility path for use in java classes */
	public String javaWebModelUtilityY;
	/** web / controller path for use in java classes */
	public String javaWebController;
	/** path and file name */
	public String webAppG;
	/** path and file name */
	public String dependenciesG;
	/** path and file name */
	public String depenHiberG;
	/** path and file name */
	public String pomPropertiesG;
	/** path and file name */
	public String springPropertiesG;
	/** path and file name */
	public String applicUserAuthenticationProviderG;
	/** path and file name */
	public String depenJacksonG;
	/** path and file name */
	public String depenHValidG;
	/** path and file name */
	public String depenValidatorG;

	// MAVEN
	/** element of Maven */
	public String mavenModel;
	/** element of Maven */
	public String mavenGroupId;
	/** element of Maven */
	public String mavenVersion;
	/** element of Maven */
	public String mavenPackage = "war";

	// VARIOUS
	/** the first part of the package, that is the network domain (2
	 * elements) + the application (1 element) */
	public String pckg;
	/** version of the artifact jar of the JPA project relating to the
	 * schema DB adopted */
	public String versioneArtifactJPA;
	/** Maven src/main/resources directory */
	public String mainResources;
	/** network domain of the company */
	public String networkDomain;
	/** list of files containing DDL, in lowercase, without extension
	 * .sql */
	public String[] ddl;
	/** name of the current controller file */
	public String groupControllerF;
	/** background color of the field containing the button */
	/* # f5f5f5 is a gray color, the default color */
	public String backColorFormAction = "#f5f5f5";
	/** Unicode character set */
	public String charset = "UTF-8";
	/** Unicode character set */
	public String charsetSenzaTrattino = "UTF8";
	/** application name in lowercase */
	public String applicationNameLower;
	/** name of the application */
	public String applicationName;
	/** webflow parameter */
	public String paramWebflow;
	/** xlbase parameter, the user group is specified, through
	 * group-search-base */
	public String searchBase;
	/** name of the column of the users table which must appear after
	 * the logon with the welcome */
	public String welcome;
	/** name of the column of the users table indicating the password */
	public String password;

	// QUARTZ
	/** elements of a quartz trigger */
	public ClockHands clockHands;
	/** list of triggers */
	public List<ClockHands> handE = new ArrayList<ClockHands>();

	// SECURITY
	/** if you qualify through userid / password, or in other ways
	 * (userpass markup value) */
	public String authenticationMode;
	/** menu to be displayed on the JSP error .jsp, by mistake during an
	 * authentication */
	public String authenticationErrorMenu;
	/** Authentication Provider methodology */
	public String authenticationProvider;
	/** password verification methodology */
	public String ldapPasswordMethod;
	/** Authentication Provider methodology */
	public String userDetailsClass;
	/** select SQL for the case of Authentication Provider =
	 * jdbc-UserDetailsManager; selection of groups */
	public String groupAuthentication;
	/** select SQL for the case of Authentication Provider =
	 * jdbc-UserDetailsManager; selection of users */
	public String usersByUserName;
	/** select SQL for the case of Authentication Provider =
	 * jdbc-UserDetailsManager; selection of authorizations */
	public String authByUserName;
	/** type of encoding and salt of the user's password */
	public String passEncoder;
	/** DB table containing the list of users; the array contains: 0)
	 * the name of the table, 1) the rail code, 2) the jndi, 3) the DB
	 * scheme, 4) the welcome column, 5) the column containing the
	 * password */
	public String[] tabUser = new String[6];
	/** index, in the general list of DB tables, of the users table */
	public int tabUserJ = -1;
	/** userid in the trivial case userid and password carved in the
	 * code, ROLE_USER case */
	public String userTrivialUSER;
	/** userid in the trivial case userid and password carved in the
	 * code, case ROLE_ADMIN */
	public String userTrivialADMIN;
	/** password in the trivial case userid and password carved in the
	 * code, ROLE_USER case */
	public String passTrivialUSER;
	/** password in the trivial case userid and password carved in the
	 * code, case ROLE_ADMIN */
	public String passTrivialADMIN;

	/** types of DBMS */
	/* FUTURE RELEASE N6 */
	// public Set<String> dbmsE = new HashSet<String>();
	/** current DBMS */
	public String dbms;
	/** DB current scheme */
	public String dbSchema;
	/** Current JNDI */
	public String jndi;

	// PROPERTIES
	/** properties */
	public CandyScrew candies;

	// INDICES
	/** index of the default (local) language, linked to markup defaulan
	 * + */
	public int defaulan;
	/** DB sites index */
	public int railK;
	/** index of the DB table */
	public int tK;
	/** index of the DB table containing the users */
	public int uK;
	/** index of the groups of controllers; controllers are grouped by
	 * prefix; the prefix is ​​the first segment of the path */
	public int cntK;

	// COLLECTIONS
	/** list of methods present as java source */
	public HashMap<String, ELEMethod> methodE = new HashMap<String, ELEMethod>();
	/** language codes, 2 characters */
	public List<StringInt> screwLanguageE = new ArrayList<StringInt>();
	/** validation messages map */
	public Map<ValidationLabelScrew, ValidationMessageScrew> validationMessageE = new HashMap<ValidationLabelScrew, ValidationMessageScrew>();
	/** languages ​​statistics map */
	public Map<Integer, List<String>> languagesStatisticE = new HashMap<Integer, List<String>>();
	/** list of DB tables */
	public List<TableOutfit> tableDBE = new ArrayList<TableOutfit>();
	/** list of correlations RequestMapping-JSP */
	public List<ControllerBelong> correlationE = new ArrayList<ControllerBelong>();
	/** list of CSS classes */
	public List<Costume> costumeE = new ArrayList<Costume>();
	/** list of KNIFE delimiters */
	public Map<String, String> knifeE = new HashMap<String, String>();
	/** list of KNIFE delimiters */
	public Map<String, String> upperE = new HashMap<String, String>();
	/** list of KNIFE delimiters */
	public Map<String, String> lowerE = new HashMap<String, String>();
	/** list of KNIFE delimiters */
	public Map<String, String> knifeXE = new HashMap<String, String>();
	/** list of KNIFE delimiters */
	public Map<String, String> upperXE = new HashMap<String, String>();
	/** list of KNIFE delimiters */
	public Map<String, String> lowerXE = new HashMap<String, String>();
	/** list of current initial directories (N3) */
	public List<String> initialDirE = new ArrayList<String>();
	/** list of created or proposed directories (N3) */
	public List<String> proposedDirE = new ArrayList<String>();

	/** ORDINARY LOGGER */
	private static final Logger logger = Logger.getLogger(Skill.class);

	/** default constructor */
	public Skill() {
		super();
	}

	/** helpful builder
	 * 
	 * @param candies various constants */
	public Skill(CandyScrew candies) {
		super();
		this.candies = candies;
		knifeE.put("java", "/* " + Cst.KNIFE + " */");
		knifeE.put("css", "/* " + Cst.KNIFE + " */");
		knifeE.put("properties", "# " + Cst.KNIFE + "");
		knifeE.put("xml", "<!-- " + Cst.KNIFE + " -->");
		knifeE.put("jsp", "<!-- " + Cst.KNIFE + " -->");
		upperE.put("java", "/* " + Cst.UPPER + " */");
		upperE.put("css", "/* " + Cst.UPPER + " */");
		upperE.put("properties", "# " + Cst.UPPER + "");
		upperE.put("xml", "<!-- " + Cst.UPPER + " -->");
		upperE.put("jsp", "<!-- " + Cst.UPPER + " -->");
		lowerE.put("java", "/* " + Cst.LOWER + " */");
		lowerE.put("css", "/* " + Cst.LOWER + " */");
		lowerE.put("properties", "# " + Cst.LOWER + "");
		lowerE.put("xml", "<!-- " + Cst.LOWER + " -->");
		lowerE.put("jsp", "<!-- " + Cst.LOWER + " -->");
		knifeXE.put("java", "/\\x2a " + Cst.KNIFE + " \\x2a/");
		knifeXE.put("css", "/\\x2a " + Cst.KNIFE + " \\x2a/");
		knifeXE.put("properties", "# " + Cst.KNIFE + "");
		knifeXE.put("xml", "<!-- " + Cst.KNIFE + " -->");
		knifeXE.put("jsp", "<!-- " + Cst.KNIFE + " -->");
		upperXE.put("java", "/\\x2a " + Cst.UPPER + " \\x2a/");
		upperXE.put("css", "/\\x2a " + Cst.UPPER + " \\x2a/");
		upperXE.put("properties", "# " + Cst.UPPER + "");
		upperXE.put("xml", "<!-- " + Cst.UPPER + " -->");
		upperXE.put("jsp", "<!-- " + Cst.UPPER + " -->");
		lowerXE.put("java", "/\\x2a " + Cst.LOWER + " \\x2a/");
		lowerXE.put("css", "/\\x2a " + Cst.LOWER + " \\x2a/");
		lowerXE.put("properties", "# " + Cst.LOWER + "");
		lowerXE.put("xml", "<!-- " + Cst.LOWER + " -->");
		lowerXE.put("jsp", "<!-- " + Cst.LOWER + " -->");
	}

	/**
	 * <p>
	 * Skill construction (part A).
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09<br>
	 * </p>
	 * 
	 * @param markupE the list of markups
	 * @param trainE the list of trains
	 * @param candies the initial properties of the application
	 * @throws ExactException standard exception */
	public void factory_A(HashMap<String, Markup> markupE,
			List<Train> trainE, CandyScrew candies)

			throws ExactException {

		applicationName = candies.appName;
		File f = new File(candies.outputYS + applicationName);
		if (f.exists() & !f.isDirectory()) {
			ExactException ce = new ExactException();
			ce.code = 1801;
			ce.datum = "The value of given application name+: «"
					+ applicationName
					+ "» does not correspond to a real directory.";
			ce.className = this.getClass().getName();
			throw ce;
		} else {
			buildDirectory(f);
		}
		applicationNameLower = applicationName.toLowerCase();
		spring = markupE.get("sv").recurrenceE.size() > 0;
		springSecurity = markupE.get("uv").recurrenceE.size() > 0;
		captcha = markupE.get("captc").recurrenceE.size() > 0;
		webFlow = markupE.get("wparams").recurrenceE.size() > 0;
		springValid = markupE.get("svalid").recurrenceE.size() > 0;
		robots = markupE.get("srobo").recurrenceE.size() > 0;
		viewController = markupE.get("sieco").recurrenceE.size() > 0;
		tiles = markupE.get("ev").recurrenceE.size() > 0;
		hibernate = markupE.get("hv").recurrenceE.size() > 0;
		jackson = markupE.get("jacksonver").recurrenceE.size() > 0;
		prettyPrint = markupE.get("pretprint").recurrenceE.size() > 0;
		hiberValid = markupE.get("hvalid").recurrenceE.size() > 0;
		i18n = markupE.get("i18n").recurrenceE.size() > 0;
		pomProperties = markupE.get("pompr").recurrenceE.size() > 0;
		dependencies = markupE.get("depen").recurrenceE.size() > 0;
		defaultAutowire = markupE.get("sdefauto").recurrenceE
				.size() > 0;
		interceptor = markupE.get("sinterce").recurrenceE.size() > 0;
		mavenBuild = markupE.get("mavbu").recurrenceE.size() > 0;
		mavenCompiler = markupE.get("mavco").recurrenceE.size() > 0;
		mavenCompilerPlugin = markupE.get("mavcp").recurrenceE
				.size() > 0;
		mavenWarPlugin = markupE.get("mavwa").recurrenceE.size() > 0;
		mavenCleanPlugin = markupE.get("mavcl").recurrenceE.size() > 0;
		matrixVariables = markupE.get("matrix").recurrenceE.size() > 0;
		mimeMapping = markupE.get("webmime").recurrenceE.size() > 0;
		errorPage = markupE.get("weberror").recurrenceE.size() > 0;
		indexJsp = markupE.get("indexjsp").recurrenceE.size() > 0;
		/* FUTURE RELEASE N6 */
		// embedded = markupE.get("hembedded").occorrenzaE.size() > 0;
		ldapService = markupE.get("xlservice").recurrenceE.size() > 0;
		signup = markupE.get("usignup").recurrenceE.size() > 0;
		hasJsp = markupE.get("jsp").recurrenceE.size() > 0;
		if (markupE.get("defaulan").recurrenceE.size() > 0) {
			defaulan = (Integer) markupE.get("defaulan").recurrenceE
					.get(0).locomotor.substance;
		} else {
			defaulan = -1;
		}
		if (markupE.get("xprovider").recurrenceE.size() > 0) {
			authenticationProvider = markupE.get(
					"xprovider").recurrenceE.get(0).locomotor.text
							.toLowerCase();
		}
		if (markupE.get("xlclass").recurrenceE.size() > 0) {
			userDetailsClass = markupE.get("xlclass").recurrenceE.get(
					0).locomotor.text;
		}
		if (markupE.get("xlpass").recurrenceE.size() > 0) {
			ldapPasswordMethod = markupE.get("xlpass").recurrenceE.get(
					0).locomotor.text;
		}
		if (authenticationProvider != null) {
			ldap = authenticationProvider.equals("ldap");
		}
		if (markupE.get("xgbac").recurrenceE.size() > 0) {
			groupAuthentication = markupE.get("xgbac").recurrenceE.get(
					0).locomotor.text;
		}
		if (markupE.get("xusers").recurrenceE.size() > 0) {
			usersByUserName = markupE.get("xusers").recurrenceE.get(
					0).locomotor.text;
		}
		if (markupE.get("xauth").recurrenceE.size() > 0) {
			authByUserName = markupE.get("xauth").recurrenceE.get(
					0).locomotor.text;
		}
		if (markupE.get("xencoder").recurrenceE.size() > 0) {
			passEncoder = markupE.get("xencoder").recurrenceE.get(
					0).locomotor.text;
		}
		if (markupE.get("uspaformadmin").recurrenceE.size() > 0) {
			String[] up = markupE.get("uspaformadmin").recurrenceE.get(
					0).locomotor.text.split("\\x2c"); // x2c is the
													  // comma
			if (up.length != 2) {
				ExactException ne = new ExactException();
				ne.code = 1815;
				ne.datum = "The markup uspaformadmin must have 2"
						+ " parameters, separated by a comma.";
				ne.className = this.getClass().getName();
				throw ne;
			} else {
				userTrivialADMIN = up[0].trim();
				passTrivialADMIN = up[1].trim();
			}
		}
		if (markupE.get("uspaformuser").recurrenceE.size() > 0) {
			String[] up = markupE.get("uspaformuser").recurrenceE.get(
					0).locomotor.text.split(",");
			if (up.length != 2) {
				ExactException ne = new ExactException();
				ne.code = 1825;
				ne.datum = "The markup uspaformuser must have 2"
						+ " parameters, separated by a comma.";
				ne.className = this.getClass().getName();
				throw ne;
			} else {
				userTrivialUSER = up[0].trim();
				passTrivialUSER = up[1].trim();
			}
		}
		for (Train t : markupE.get("odefcss").recurrenceE) {
			Costume costume = new Costume(t);
			costumeE.add(costume);
		}
		for (Train t : markupE.get("qjobname").recurrenceE) {
			clockHands = new ClockHands(t.wagonE.get("qsimple"),
					t.wagonE.get("qcron"), t.locomotor, t.locomotor,
					t.wagonE.get("hrail"));
			String r = t.wagonE.get("hrail").text;
			int rJ = 0;
			for (; rJ < markupE.get("hdefrail").recurrenceE
					.size(); rJ++) {
				if (r.equals(markupE.get("hdefrail").recurrenceE.get(
						rJ).locomotor.text)) {
					break;
				}
			}
			if (rJ == markupE.get("hdefrail").recurrenceE.size()) {
				ExactException ne = new ExactException();
				ne.code = 1812;
				ne.datum = "The markup «hrail» of «quartz»"
						+ " presents a value " + r
						+ ", but it does not exist"
						+ " among the «hdefrail» definitions.";
				ne.className = this.getClass().getName();
				throw ne;
			}
			handE.add(clockHands);
		}
		hasUseridPassword = markupE.get("userpass").recurrenceE
				.size() > 0;
		if (hasUseridPassword) {
			authenticationMode = markupE.get("userpass").recurrenceE
					.get(0).locomotor.text;
			if (markupE.get("userpass").recurrenceE.get(0).wagonE
					.containsKey("bmenu")) {
				authenticationErrorMenu = markupE.get(
						"userpass").recurrenceE.get(0).wagonE.get(
								"bmenu").text;
			}
		}
		internalProperties = markupE.get("uintp").recurrenceE
				.size() > 0;
		if (springSecurity & !spring) {
			ExactException ne = new ExactException();
			ne.code = 1800;
			ne.datum = "Spring Security cannot be applied for"
					+ " without having first declared Spring by means "
					+ "of sv markup.";
			ne.className = this.getClass().getName();
			throw ne;
		}
		for (int i = 0; i < trainE.size(); i++) {
			hasForm = false;
			Train train = trainE.get(i);
			if (train.locomotor.stub.equals("sv")) {
				springVersion = train.locomotor.text;
				String[] x = springVersion.split("\\x2e");
				springVersion1m = Integer.valueOf(x[0].trim());
			} else if (train.locomotor.stub.equals("appse")) {
				applicationServer = train.locomotor.text;
			} else if (train.locomotor.stub.equals("jeev")) {
				jeeVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("uv")) {
				int v = ((Integer) (train.locomotor.substance))
						.intValue() / 1000;
				springSecurityReductVersion = (v / 1000) + "." + v
						% 1000;
				springSecurityVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("hv")) {
				int v = ((Integer) (train.locomotor.substance))
						.intValue() / 1000;
				hibernateReductVersion = String.valueOf(v / 1000);
				hibernateVersion = train.locomotor.text;
				String[] x = hibernateVersion.split("\\x2e");
				hibernateVersion1m = Integer.valueOf(x[0].trim());
				jpaVersion = Integer.valueOf(train.wagonE.get(
						"hjpav").text);
			} else if (train.locomotor.stub.equals("jacksonver")) {
				jacksonVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("hvalid")) {
				hiberValidVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("charset")) {
				int j = 0;
				String maiu = train.locomotor.text.toUpperCase();
				for (; j < Universal.charsetE.length; j++) {
					if (Universal.charsetE[j].equals(maiu)) {
						break;
					}
				}
				if (j == Universal.charsetE.length) {
					ExactException ce = new ExactException();
					ce.code = 1840;
					ce.datum = "The value of the charset markup is wrong,"
							+ " it isn't present in the list: " + trainE
									.get(i).locomotor.text;
					ce.className = this.getClass().getName();
					throw ce;
				} else {
					train.locomotor.text = maiu.toUpperCase();
				}
				charset = train.locomotor.text;
				charsetSenzaTrattino = Strings.replaceFirst(charset,
						"-", "");
			} else if (train.locomotor.stub.equals("ev")) {
				tilesVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("colorform")) {
				backColorFormAction = train.locomotor.text;
			} else if (train.locomotor.stub.equals("mavco")) {
				mavenCompilerVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("mavcp")) {
				mavenCompilerPluginVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("mavwa")) {
				mavenWarPluginVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("mavcl")) {
				mavenCleanPluginVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("captc")) {
				captchaVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("mavmo")) {
				mavenModel = train.locomotor.text;
			} else if (train.locomotor.stub.equals("mavgr")) {
				mavenGroupId = train.locomotor.text;
			} else if (train.locomotor.stub.equals("mv")) {
				mavenVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("filte")) {
				filter = true;
			} else if (train.locomotor.stub.equals("antisamy")) {
				antiSamy = true;
			} else if (train.locomotor.stub.equals("log4j")) {
				log4jVers = train.locomotor.text;
			} else if (train.locomotor.stub.equals("quartz")) {
				quartzVers = train.locomotor.text;
			} else if (train.locomotor.stub.equals("wv")) {
				webflowVersion = train.locomotor.text;
			} else if (train.locomotor.stub.equals("wparams")) {
				paramWebflow = train.locomotor.text;
			} else if (train.locomotor.stub.equals("xlbase")) {
				searchBase = train.locomotor.text;
			} else if (train.locomotor.stub.equals("requmap")) {
				Map<String, Wagon> wE = train.wagonE;
				int jspJ = 0;
				List<Train> jspE = markupE.get("jsp").recurrenceE;
				String pathJsp = "";
				/* if I have not specified the goal, it means that the
				 * request mapping oil path and the JSP path coincide */
				if (wE.get("goal") == null) {
					pathJsp = train.locomotor.text;
				} else {
					pathJsp = wE.get("goal").text;
				}
				/* identification of the destination JSP */
				for (jspJ = 0; jspJ < jspE.size(); jspJ++) {
					if (jspE.get(jspJ).locomotor.text.equals(pathJsp)) {
						break;
					}
				}
				JspKit jspKit = null;
				/* for the "not found" case I make 2 different messages
				 * depending on whether the goal has been specified or
				 * not */
				if (jspJ == jspE.size() & wE.get("goal") == null) {
					ExactException ne = new ExactException();
					ne.code = 1809;
					ne.datum = "For the «requmap+" + trainE.get(
							i).locomotor.text
							+ "» I assume an identical JSP path; but it"
							+ " does not exist in the JSPs list.";
					ne.className = this.getClass().getName();
					throw ne;
				} else if (jspJ == jspE.size()) {
					ExactException ne = new ExactException();
					ne.code = 1841;
					ne.datum = "The JSP indicated in goal+" + pathJsp
							+ " for the «requmap+" + trainE.get(
									i).locomotor.text
							+ "» does not exist.";
					ne.className = this.getClass().getName();
					throw ne;
				} else {
					jspKit = (JspKit) jspE.get(
							jspJ).locomotor.substance;
				}
				String pathRedirect = wE.get("redirect") == null ? ""
						: wE.get("redirect").text;
				/* only after I have processed all the request maps can
				 * I verify that the redirect request map really
				 * exists */

				RequestMap rm = null;
				if (train.locomotor.text.equals(jspKit.path + "/"
						+ jspKit.fileName)) {
					ExactException ne = new ExactException();
					ne.code = 1804;
					ne.datum = "The path indicated in goal+" + wE.get(
							"goal").text
							+ " è inutile, si prega di cancellarlo."
							+ " In fact, it is already adopted by default.";
					ne.className = this.getClass().getName();
					throw ne;
				} else if (wE.get("model") != null) {
					jspKit.requestMapE.get(0).tipo = 2;
					rm = new RequestMap(trainE.get(i).locomotor.text,
							jspKit.path + "/" + jspKit.fileName,
							pathRedirect, 2);
					jspKit.requestMapE.add(rm);
				} else {
					if (jspKit.controlE.size() > 0) {
						jspKit.jspType = Cst.FORM;
					} else if (jspKit.requestMapE.size() == 0) {
						jspKit.jspType = Cst.PLAIN;
					} else {
						jspKit.jspType = jspKit.requestMapE.get(0).tipo;
					}
					rm = new RequestMap(trainE.get(i).locomotor.text,
							jspKit.path + "/" + jspKit.fileName,
							pathRedirect, jspKit.jspType);
					jspKit.requestMapE.add(rm);
				}
			} else if (train.locomotor.stub.equals("language")) {
				int j = 0;
				String minus = train.locomotor.text.toLowerCase();
				for (; j < Universal.languageE.length; j++) {
					if (Universal.languageE[j][1].equalsIgnoreCase(
							minus)) {
						break;
					}
				}
				if (j == Universal.languageE.length) {
					ExactException ne = new ExactException();
					ne.code = 1802;
					ne.datum = "The value of the markup \"language\" is wrong,"
							+ " it isn't present in the list of language codes"
							+ " ISO 639-1: " + trainE.get(
									i).locomotor.text + ".";
					ne.className = this.getClass().getName();
					throw ne;
				} else {
					train.locomotor.text = minus;
					screwLanguageE.add(new StringInt(
							train.locomotor.text, j));
				}

				// END OF REQUMAP PROCESSING

				// PROCESS OF THE MARKUP VALLABEL +

			} else if (train.locomotor.stub.equals("vallabel")) {
				/* ccJ is the numeric code of the language; the value -1
				 * is used when I have not declared a language code,
				 * then I want the default value */
				int lcJ = -1;
				if (train.wagonE.get("vallang") != null) {
					int j = 0;
					for (; j < Universal.languageE.length; j++) {
						if (train.wagonE.get("vallang").text
								.equalsIgnoreCase(
										Universal.languageE[j][1])) {
							break;
						}
					}
					lcJ = j;
					if (lcJ == defaulan) {
						ExactException ce = new ExactException();
						ce.code = 1833;
						ce.datum = "A vallang+ markup defines «"
								+ train.wagonE.get("vallang").text
								+ "», but this value is declared as"
								+ " default by defaulan+ markup."
								+ " Please omit this vallang+"
								+ train.wagonE.get("vallang").text
								+ ".";
						ce.className = this.getClass().getName();
						throw ce;
					}
				}
				/* the validation label is the couple label-code of
				 * language */
				ValidationLabelScrew vl = new ValidationLabelScrew(
						train.locomotor.text, lcJ);
				/* this couple must not appear two times */
				if (validationMessageE.containsKey(vl)) {
					ExactException ne = new ExactException();
					ne.code = 1829;
					ValidationMessageScrew vs = validationMessageE.get(
							vl);
					if (lcJ == -1) {
						ne.datum = "Duplicated couple label-language in a"
								+ " validation message: " + vs.vl.label
								+ " (default value for language code).";
					} else {
						ne.datum = "Duplicated couple label-language in a"
								+ " validation message: " + vs.vl.label
								+ "/"
								+ Universal.languageE[vs.vl.languageCodeIndex];
					}

					ne.className = this.getClass().getName();
					throw ne;
				} else {
					/* finally, the object vl is valid */
					validationMessageE.put(vl,
							new ValidationMessageScrew(vl, train.wagonE
									.get("valmess").text));
					List<String> lsE = languagesStatisticE.get(lcJ);
					/* if the ccJ code has not yet been entered ... */
					if (lsE == null) {
						/* .. then enter it */
						ArrayList<String> mE = new ArrayList<String>();
						mE.add(train.locomotor.text + "=" + train.wagonE
								.get("valmess").text);
						languagesStatisticE.put(lcJ, mE);
					} else {
						/* ... otherwise record its message */
						lsE.add(train.locomotor.text + "="
								+ train.wagonE.get("valmess").text);
						languagesStatisticE.replace(lcJ, lsE);
					}
				}

				// END OF THE PROCESS OF THE MARKUP VALLABEL +

			} else if (train.locomotor.stub.equals("company")) {
				networkDomain = train.locomotor.text;
				if (networkDomain.startsWith(".") | networkDomain
						.endsWith(".")) {
					ExactException ne = new ExactException();
					ne.code = 1803;
					ne.datum = "The value of markup «company» is wrong: "
							+ networkDomain;
					ne.className = this.getClass().getName();
					throw ne;
				}
			} else if (train.locomotor.stub.equals("jsp")) {
				JspKit jspKit = (JspKit) trainE.get(
						i).locomotor.substance;
				logger.trace(Candies.LF + Cst.CUT0
						+ "I am processing the JSP " + jspKit.path + "/"
						+ jspKit.fileName + "." + jspKit.extension);
				if (jspKit.controlE.size() > 0) {
					hasForm = true;
				}
				if (train.wagonE.get("string") != null) {
					String[] wE = train.wagonE.get("string").text.split(
							"\\x2c");
					for (String w : wE) {
						jspKit.stringPropertyE.add(new JspBeanElement(w
								.trim(), "String", false, "", null,
								null, null));
					}
				}
				if (train.wagonE.get("arraystring") != null) {
					String[] wE = train.wagonE.get("arraystring").text
							.split("\\x2c");
					for (String w : wE) {
						jspKit.arrayStringPropertyE.add(
								new JspBeanElement(w.trim(),
										"ArrayList<String>", false, "",
										null, null, null));
					}
				}
				if (train.wagonE.get("integer") != null) {
					String[] wE = train.wagonE.get("integer").text
							.split("\\x2c");
					for (String w : wE) {
						jspKit.integerPropertyE.add(new JspBeanElement(w
								.trim(), "Integer", false, "", null,
								null, null));
					}
				}
				if (train.wagonE.get("long") != null) {
					String[] wE = train.wagonE.get("long").text.split(
							"\\x2c");
					for (String w : wE) {
						jspKit.longPropertyE.add(new JspBeanElement(w
								.trim(), "Long", false, "", null, null,
								null));
					}
				}
				if (train.wagonE.get("boolean") != null) {
					String[] wE = train.wagonE.get("boolean").text
							.split("\\x2c");
					for (String w : wE) {
						jspKit.booleanPropertyE.add(new JspBeanElement(w
								.trim(), "Boolean", false, "", null,
								null, null));
					}
				}
				Wagon v = train.wagonE.get("dress");
				if (v != null) {
					int m = 0;
					List<Train> fE = markupE.get("method").recurrenceE;
					for (; m < fE.size(); m++) {
						if (fE.get(m).locomotor.text.equals(v.text)) {
							break;
						}
					}
					if (m == fE.size()) {
						ExactException ne = new ExactException();
						ne.code = 1816;
						ne.datum = "For JSP «" + trainE.get(
								i).locomotor.text
								+ "», the indication of «dress+"
								+ v.text + "» does not exist among"
								+ " the declared methods.";
						ne.className = this.getClass().getName();
						throw ne;
					}
					jspKit.methodE.add(v);
				}
				Wagon rv = train.wagonE.get("refresh");
				if (rv != null) {
					jspKit.refresh = Integer.valueOf(rv.text);
				}
				Wagon ptv = train.wagonE.get("pagetitle");
				if (ptv != null) {
					jspKit.pageTitle = ptv.text;
				}
				Wagon crudv = train.wagonE.get("crud");
				if (crudv != null) {
					jspKit.crud = true;
				}
			}
		}

		projectFactory();
		File dotClasspath = new File(SCREW_MAVEN + sep + ".classpath");
		int railQ = markupE.get("hdefrail").recurrenceE.size();
		String[] o = new String[railQ];
		for (int i = 0; i < railQ; i++) {
			Train train = markupE.get("hdefrail").recurrenceE.get(i);
			String jndi = train.wagonE.get("hjndi").text;
			String dbschema = train.wagonE.get("hdbschema").text;
			o[i] = jndi + "-" + dbschema;
		}
		correctFile(dotClasspath, "path=\"/", "xxxx-xxxx",
				Candies.SURGERY1, o, new File(eclipseProjectY
						+ ".classpath"), "UTF-8");
		// LATEST CHECKS
		for (int i = 0; i < trainE.size(); i++) {
			Train train = trainE.get(i);
			if (train.locomotor.stub.equals("valcons")) {
				for (int lJ : languagesStatisticE.keySet()) {
					ValidationLabelScrew vl = new ValidationLabelScrew(
							train.wagonE.get("valtag").text, lJ);
					if (validationMessageE.get(vl) == null) {
						ExactException ce = new ExactException();
						if (lJ == -1) {
							ce.datum = "In the list of messages in language «"
									+ Universal.languageE[defaulan][1]
									+ "», the label «" + train.wagonE
											.get("valtag").text
									+ "» is missing.";
						} else {
							ce.datum = "In the list of messages in language «"
									+ Universal.languageE[lJ][1]
											.toLowerCase()
									+ "», the label «" + train.wagonE
											.get("valtag").text
									+ "» is missing.";
						}
						ce.code = 1839;
						ce.className = this.getClass().getName();
						throw ce;
					}
				}
			}
		}
		for (int lJ : languagesStatisticE.keySet()) {
			String s = "";
			for (ValidationLabelScrew m : validationMessageE.keySet()) {
				if (m.languageCodeIndex == lJ) {
					s += m.label + "=" + validationMessageE.get(
							m).message + Candies.LF;
				}
			}
			s += knifeE.get("properties");
			String y = candies.outputYS + applicationName
					+ "/src/main/resources/";
			String nomeFileOutput = "messagesScrewValid";
			if (lJ > -1) {
				nomeFileOutput += "_" + Universal.languageE[lJ][1]
						.toLowerCase();
			}
			nomeFileOutput += ".properties";
			try {
				toTarget(y, nomeFileOutput, s, nomeFileOutput,
						candies.boxYS + "recycleBin", "properties");
				// FileComponent.aggiungiFile (outputfilename,
				// outputFileName, y, candies, candies.boxYS
				// + "trash", this);
			} catch (FileNotFoundException e) {
				ExactException ce = new ExactException();
				ce.code = 1837;
				ce.datum = "File not found exception.";
				ce.className = this.getClass().getName();
				throw ce;
			} catch (IOException e) {
				ExactException ce = new ExactException();
				ce.code = 1838;
				ce.datum = "I/O exception.";
				ce.className = this.getClass().getName();
				throw ce;
			}
		}

		Iterator<Map.Entry<Integer, List<String>>> iterator = languagesStatisticE
				.entrySet().iterator();
		int k = 0;
		int primaFrequenza = 0;
		while (iterator.hasNext()) {
			Map.Entry<Integer, List<String>> entry = iterator.next();
			if (k == 0) {
				primaFrequenza = entry.getValue().size();
			} else if (entry.getValue().size() != primaFrequenza) {
				ExactException ce = new ExactException();
				ce.code = 1830;
				ce.datum = "The quantity of messages for language «"
						+ Universal.languageE[entry.getKey()
								.intValue()][1] + "» (" + entry
										.getValue().size()
						+ ") is different from the others. "
						+ "Please count again.";
				ce.className = this.getClass().getName();
				throw ce;
			}
			k++;
		}
		if (screwLanguageE.size() > 0) {
			if (screwLanguageE.size() != primaFrequenza) {
				ExactException ce = new ExactException();
				ce.code = 1831;
				ce.datum = "The quantity of markup language+ ("
						+ screwLanguageE.size()
						+ ") is different from the quantity of languages"
						+ " declared by vallabel+ (" + primaFrequenza
						+ "). " + "Please count again.";
				ce.className = this.getClass().getName();
				throw ce;
			} else {
				for (StringInt x : screwLanguageE) {
					if (languagesStatisticE.get(x.i) == null) {
						ExactException ce = new ExactException();
						ce.code = 1832;
						ce.datum = "The markup «language+" + x.s
								+ "» has no coincidence in the markups"
								+ " vallabel+.";
						ce.className = this.getClass().getName();
						throw ce;
					}
				}
			}
		}
		if (springVersion1m > 3 & jpaVersion == 1) {
			ExactException ce = new ExactException();
			ce.code = 1828;
			ce.datum = "If JPA has version 1, you need a version of"
					+ " Spring < 4; currently Spring is "
					+ springVersion;
			ce.className = this.getClass().getName();
			throw ce;
		}
		if (hasUseridPassword && tabUser == null
				&& authenticationProvider != null
				&& !authenticationProvider.equals("ldap")) {
			ExactException ce = new ExactException();
			ce.code = 1806;
			ce.datum = "The \"utabuser\" markup must be used specifying"
					+ " the name of the table.";
			ce.className = this.getClass().getName();
			throw ce;
		}
		if (tabUser[0] != null & authenticationProvider == null) {
			ExactException ce = new ExactException();
			ce.code = 1807;
			ce.datum = "The \"xprovider\" markup must be used "
					+ "specifying the authentication method.";
			ce.className = this.getClass().getName();
			throw ce;
		}
	}

	/**
	 * <p>
	 * Skill construction (part B).
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09<br>
	 * </p>
	 * 
	 * @param markupE the list of markups
	 * @param trainE the train list
	 * @throws ExactException standard exception */
	public void factory_B(HashMap<String, Markup> markupE,
			List<Train> trainE)

			throws ExactException {

		for (int i = 0; i < trainE.size(); i++) {
			if (trainE.get(i).locomotor.stub.equals("utabuser")) {
				tabUser[0] = Mix.uppercaseFirstChar(trainE.get(
						i).locomotor.text);
				int k = 0;
				for (; k < tableDBE.size(); k++) {
					if (tabUser[0].equals(tableDBE.get(k).entityName)) {
						break;
					}
				}
				if (k == tableDBE.size()) {
					ExactException ce = new ExactException();
					ce.code = 1814;
					ce.datum = "The markup «utabuser»"
							+ " presents the value " + tabUser[0]
							+ ", but it does not exist"
							+ " amonf the definitions of the DB tables.";
					ce.className = this.getClass().getName();
					throw ce;
				}
				if (trainE.get(i).wagonE.get("hrail") == null) {
					ExactException ce = new ExactException();
					ce.code = 1810;
					ce.datum = "The markup «utabuser» is not followed"
							+ " by the markup «hrail».";
					ce.className = this.getClass().getName();
					throw ce;
				} else {
					tabUser[1] = trainE.get(i).wagonE.get("hrail").text;
					k = 0;
					for (; k < markupE.get("hdefrail").recurrenceE
							.size(); k++) {
						if (tabUser[1].equals(markupE.get(
								"hdefrail").recurrenceE.get(
										k).locomotor.text)) {
							break;
						}
					}
					if (k == markupE.get("hdefrail").recurrenceE
							.size()) {
						ExactException ce = new ExactException();
						ce.code = 1811;
						ce.datum = "The markup «hrail» of «utabuser»"
								+ " presents the value " + tabUser[1]
								+ ", but it does not exist"
								+ " among the definitions «hdefrail».";
						ce.className = this.getClass().getName();
						throw ce;
					}
					tabUser[2] = markupE.get("hdefrail").recurrenceE
							.get(k).wagonE.get("hjndi").text;
					tabUser[3] = markupE.get("hdefrail").recurrenceE
							.get(k).wagonE.get("hdbschema").text;
					int j = 0;
					for (; j < tableDBE.size(); j++) {
						if (tableDBE.get(j).entityName.equalsIgnoreCase(
								tabUser[0]) & tableDBE.get(j).jndi
										.equalsIgnoreCase(tabUser[2])
								& tableDBE.get(j).dbSchema
										.equalsIgnoreCase(tabUser[3])) {
							break;
						}
					}
					if (j == tableDBE.size()) {
						ExactException ce = new ExactException(
								"I have not found the table used to "
										+ "verify the user's account "
										+ tabUser[0] + ", jndi="
										+ tabUser[2] + ", DB schema="
										+ tabUser[3], 2100, this
												.getClass().getName(),
								"");
						throw ce;

					} else {
						uK = j;
					}
					TableOutfit ct = tableDBE.get(uK);
					welcome = trainE.get(i).wagonE.get("uwelcome").text;
					boolean presenza = FileComponent.checkColumn(ct,
							welcome);
					if (!presenza) {
						ExactException ce = new ExactException(
								"In the file " + ct.entityName + ".java"
										+ " could not find the DB column «"
										+ welcome + "»", 2101, this
												.getClass().getName(),
								"factory_B");
						throw ce;

					}
					password = trainE.get(i).wagonE.get(
							"upassword").text;
					presenza = FileComponent.checkColumn(ct, password);
					if (!presenza) {
						ExactException ce = new ExactException(
								"Nel file " + ct.entityName + ".java"
										+ " non ho trovato la column di DB «"
										+ password, 2102, this
												.getClass().getName(),
								"");
						throw ce;
					}
				}
			}
		}
	}

	/**
	 * <p>
	 * Construction of the methods whose source is fully present in the
	 * ele file, defined with the "method" markup.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09<br>
	 * </p>
	 * 
	 * @param markupE the list of markups
	 * @param trainE the train list
	 * @throws ExactException standard exception */
	public void methodsFactory(HashMap<String, Markup> markupE,
			List<Train> trainE)

			throws ExactException {

		ExactException ne = new ExactException();
		for (int i = 0; i < trainE.size(); i++) {
			Train t = trainE.get(i);
			if (t.locomotor.stub.equals("method")) {
				String sorgente = null;
				if (candies.inside) {
					sorgente = (String) t.locomotor.substance;
				} else if (t.locomotor.substance != null
						& !((String) (t.locomotor.substance))
								.isEmpty()) {
					ne.datum = "The method " + Mix.dress_A(
							t.locomotor.text)
							+ " has a source code declared"
							+ " in the ELE file,"
							+ " but this is not allowed by "
							+ "the \"inside\" property.";
					ne.code = 1824;
					ne.className = this.getClass().getName();
					throw ne;
				}
				List<TableOutfit> daoE = new ArrayList<TableOutfit>();
				if (t.wagonE.get("dao") != null) {
					String[][] dE = (String[][]) t.wagonE.get(
							"dao").substance;
					for (String s : dE[0]) {
						if (s.startsWith(Cst.IRAILU) & s.endsWith(
								"Dao")) {
							s = s.substring(5, s.length() - 3);
							int nr = -1;
							String tabella = null;
							if (s.matches(
									"\\d{1}\\p{Alpha}\\p{Graph}*")) {
								nr = Integer.valueOf(s.substring(0, 1));
								tabella = s.substring(1);
							} else if (s.matches(
									"\\d{2}\\p{Alpha}\\p{Graph}*")) {
								nr = Integer.valueOf(s.substring(0, 2));
								tabella = s.substring(2);
							}
							String tab1 = Cst.RAIL + nr + tabella;
							int l = 0;
							for (; l < tableDBE.size(); l++) {
								String entity = tableDBE.get(
										l).railLowercase + tableDBE.get(
												l).entityNameU;
								String tableName = tableDBE.get(
										l).railLowercase + tableDBE.get(
												l).tableNameU;
								if (tab1.equals(entity) | tab1.equals(
										tableName)) {
									break;
								}
							}
							if (l == tableDBE.size()) {
								Mix.discloseInfo("The object " + Mix
										.dress_A("I" + Mix
												.uppercaseFirstChar(
														tab1))
										+ " doesn't correspond to any"
										+ " of the DB tables declared"
										+ " in the JPA project.",
										"Error", logger);
							} else {
								daoE.add(tableDBE.get(l));
							}
						} else {
							ne.datum = "The method " + Mix.dress_A(
									t.locomotor.text)
									+ " has a dao+ containing uncorrect"
									+ " elements.";
							ne.code = 1826;
							ne.className = this.getClass().getName();
							throw ne;
						}
					}
				}
				String argoGrande = "", argoPiccolo = "";
				for (TableOutfit d : daoE) {
					if (jpaVersion == 1) {
						argoGrande += Candies.LF + Candies.TAB
								+ Candies.TAB + Candies.TAB + "I"
								+ d.railUppercase + d.entityNameU
								+ "Dao " + d.railLowercase
								+ d.entityName + "Dao" + ", ";
					} else {
						argoGrande += Candies.LF + Candies.TAB
								+ Candies.TAB + Candies.TAB + "I"
								+ d.railUppercase + d.entityNameU
								+ "Dao<" + d.pathDots + "."
								+ d.entityNameU + "> " + d.railLowercase
								+ d.entityName + "Dao" + ", ";
					}
					argoPiccolo += Candies.LF + Candies.TAB
							+ Candies.TAB + Candies.TAB
							+ d.railLowercase + d.entityName + "Dao"
							+ ", ";
				}
				/* cut the last 2 characters (comma and space) */
				if (argoGrande.length() > 2) {
					argoGrande = argoGrande.substring(0, argoGrande
							.length() - 2);
				}
				if (argoPiccolo.length() > 2) {
					argoPiccolo = argoPiccolo.substring(0, argoPiccolo
							.length() - 2);
				}
				List<String> classiE = new ArrayList<String>();
				if (t.wagonE.get("others") != null) {
					String[] oE = (String[]) t.wagonE.get(
							"others").substance;
					for (String s : oE) {
						String iniziale = s.substring(0, 1);
						if (!iniziale.equals(iniziale.toUpperCase())) {
							ne.datum = "The method «" + t.locomotor.text
									+ "» has an «others» markup "
									+ "which contains elements"
									+ " with a non-capital initial.";
							ne.code = 1827;
							ne.className = this.getClass().getName();
							throw ne;
						}
						classiE.add(s);
					}
				}
				ELEMethod m = new ELEMethod(t.locomotor.text, sorgente,
						argoGrande, argoPiccolo, daoE, classiE);
				methodE.put(m.name, m);
			}
		}
	}

	private void projectFactory()

			throws ExactException {

		eclipseProjectY = Mix.dress_CU(candies.outputYS
				+ applicationNameLower);
		buildDirectory(eclipseProjectY);
		File screwMaven = new File(SCREW_MAVEN);
		if (!screwMaven.exists()) {
			throw new ExactException("The directory " + eclipseProjectY
					+ "screwMaven was not found.", 1101, "Skill",
					"projectFactory");
		}
		File dotProject = new File(SCREW_MAVEN + sep + ".project");
		String[] o = new String[1];
		o[0] = applicationNameLower;
		correctFile(dotProject, "<name>", "XappnameX", Candies.SURGERY1,
				o, new File(eclipseProjectY + ".project"), "UTF-8");
		sorgentiY = eclipseProjectY + "src";
		buildDirectory(sorgentiY);
		mainY = sorgentiY + "/main";
		buildDirectory(mainY);
		mainJavaY = mainY + "/java";
		buildDirectory(mainJavaY);
		mainResources = mainY + "/resources";
		buildDirectory(mainResources);
	}

	/**
	 * <p>
	 * Creation date: 2020-09-27<br>
	 * Last updated: 2020-09-27<br>
	 * Class: Skill
	 * 
	 * @author Massimo Maglioni
	 *         <p>
	 *         Description: case SURGERY1: one time, substitution of
	 *         target with the new application name;
	 *         </p>
	 * @param input file to be corrected
	 * @param prefix string preceding the gtarget to correct
	 * @param target string to be corrected
	 * @param op correction mode
	 * @param objectE string that replaces the target
	 * @param destination output file
	 * @param unicode chatacter code Unicode
	 * @throws ExactException standard exception */
	private void correctFile(File input, final String prefix,
			final String target, final int op, final String[] objectE,
			File destination, String unicode)

			throws ExactException {

		String s = Equipment.oneStringUnicode_A(input, unicode);
		String b = "";
		if (objectE.length == 1) {
			if (op == Candies.SURGERY1) {
				b = s.replaceFirst(prefix + target, prefix
						+ objectE[0]);
			}
		} else {
			if (op == Candies.SURGERY1) {
				List<String> a = ReadMyFile.zebra_C(input, unicode);
				for (int i = 0; i < a.size(); i++) {
					int j = a.get(i).indexOf(target);
					if (j == -1) {
						b += a.get(i) + Candies.LF;
					} else {
						for (int k = 0; k < objectE.length; k++) {
							b += a.get(i).replaceFirst(prefix + target,
									prefix + objectE[k]) + Candies.LF;
						}
					}
				}
				b = b.substring(0, b.length() - 1);
			}
		}
		Equipment.writeFileFromOneStringUnicode_A(destination, b,
				unicode);
	}

	/**
	 * <p>
	 * Create a directory, if it doesn't already exist, after making
	 * sure it isn't a file.<br>
	 * It can only create one directory at a time.<br>
	 * Example: I have to create directory b in path C:/a;<br>
	 * I must put the string: "C:/a/b" as the argument of the method,
	 * and I must first verify that C:/a exists.<br>
	 * </p>
	 * <p>
	 * Creation date: 2020-09-03<br>
	 * Last updated: 2020-09-08
	 * </p>
	 * <p>
	 * Modifications:<br>
	 * </p>
	 * 
	 * @param path to the directory to be built, complete with path */
	public void buildDirectory(final String path) {

		File cradle = new File(path);
		buildDirectory(cradle);
	}

	/**
	 * <p>
	 * Overload of the preceding method.
	 * </p>
	 * <p>
	 * Creation date: 2020-09-03<br>
	 * Last updated: 2020-09-08
	 * </p>
	 * <p>
	 * Modifications:<br>
	 * </p>
	 * 
	 * @param cradle directory to be created */
	public void buildDirectory(File cradle) {

		if (cradle.isFile()) {
			cradle.delete();
		} else {
			proposedDirE.add(cradle.getPath());
		}
		if (!cradle.exists()) {
			cradle.mkdir();
		}
	}

	/**
	 * <p>
	 * Creation date: 2020-04-20<br>
	 * Last updated: 2020-06-26<br>
	 * Class: FileComponent
	 * 
	 * @author Massimo Maglioni
	 *         <p>
	 *         Description: This method analyzes the files to be
	 *         written, compares them with the existing ones, then
	 *         writes what is necessary.
	 *         </p>
	 * @param pre_existentPath pre-existent path
	 * @param pre_existentFilename the name of the output file, that is
	 *        the one where the material is poured
	 * @param materialeProdottoDaScrewdriver code producted by
	 *        Screwdriver application
	 * @param nomeFileOrigine this name would not be necessary, because
	 *        the string is all contained in input material; however,
	 *        for the eventual signaling to the user, in the
	 *        "permission" method
	 * @param recycleBinY the path of the directory with the function of
	 *        trash
	 * @param type the extension of the output file; only java,
	 *        properties, xml and jsp are allowed
	 * @throws ExactException standard exception
	 * @throws FileNotFoundException standard exception
	 * @throws IOException standard exception */
	public void toTarget(final String pre_existentPath,
			String pre_existentFilename,
			String materialeProdottoDaScrewdriver,
			final String nomeFileOrigine, final String recycleBinY,
			final String type)

			throws ExactException, FileNotFoundException, IOException {

		/* the 3 strings, although identical, are repeated: those
		 * without X are used for simple searches for strings (indexOf,
		 * endswith, etc.), the one with the X for operations with the
		 * Pattern class */

		String knife = knifeE.get(type);
		String upper = upperE.get(type);
		String lower = lowerE.get(type);
		String knifeX = knifeXE.get(type);
		String upperX = upperXE.get(type);
		String lowerX = lowerXE.get(type);
		File preExistent = null;
		String outExt = Mix.estraiExtension(pre_existentFilename);
		/* the default extension is .java */
		if (outExt == null) {
			outExt = "java";
			pre_existentFilename = pre_existentFilename + "." + outExt;
		}
		/* the extension of the existing file must be one of those
		 * provided */
		if (!outExt.equals("java") & !outExt.equals("properties")
				& !outExt.equals("jsp") & !outExt.equals("xml")
				& !outExt.equals("css")) {
			throw new ExactException("The file " + pre_existentFilename
					+ " in directory " + pre_existentPath
					+ " is declared with an extension not allowed: "
					+ outExt, 1103, "FileComponent", "");
		}
		if (!outExt.equals(type)) {
			throw new ExactException("The file " + pre_existentFilename
					+ " in directory " + pre_existentPath
					+ " is declared with an extension «" + outExt
					+ "» not corresponding to the type «" + type + "»",
					1108, "FileComponent", "");
		}
		String inExt = Mix.estraiExtension(nomeFileOrigine);
		/* the extension of the produced file must be one of those
		 * provided */
		if (!inExt.equals("java") & !inExt.equals("properties") & !inExt
				.equals("jsp") & !inExt.equals("xml") & !inExt.equals(
						"txt") & !inExt.equals("css")) {
			throw new ExactException("The original file "
					+ nomeFileOrigine
					+ " is declared with an extension not allowed: "
					+ inExt, 1104, "FileComponent", "");
		}
		if (!inExt.equals("txt") & !inExt.equals(type)) {
			throw new ExactException("The original file "
					+ nomeFileOrigine
					+ " it is declared with an extension " + Mix
							.dress_A(inExt)
					+ " not corresponding to the type " + Mix.dress_A(
							type) + ".", 1109, "FileComponent", "");
		}
		/* check that there is no confusion between the old and the new
		 * file; the new one can only contain the string "knife" */
		if (materialeProdottoDaScrewdriver.indexOf(upper) > -1
				| materialeProdottoDaScrewdriver.indexOf(lower) > -1) {
			throw new ExactException("The original file «"
					+ nomeFileOrigine
					+ "» cannot contain either the string " + Mix
							.dress_A(upper) + "  or the string " + Mix
									.dress_A(lower) + ".", 1105,
					"FileComponent", "");
		}
		preExistent = new File(Mix.dress_C(pre_existentPath)
				+ pre_existentFilename);
		/* if the output file still does not exist, liquidate
		 * everything */
		if (!preExistent.exists()) {
			/* note that the position of knife, that is, the column in
			 * the row, causes the same position for the upper string;
			 * originally knife should be after a TAB */
			String doublet = "";
			// if (!outExt.equals("properties")) {
			// doublet += Candies.TAB;
			// }
			doublet += upper + Candies.LF;
			if (!outExt.equals("properties")) {
				doublet += Candies.TAB;
			}
			doublet += lower;
			String trasformato = materialeProdottoDaScrewdriver
					.replaceAll(knifeX, doublet);
			Equipment.writeFileFromOneStringUnicode_A(preExistent,
					trasformato, "UTF-8");
			return;
		}
		/* at this point we know that the worked file already existed */
		/* correction necessary to avoid breakdowns during
		 * construction */
		if (materialeProdottoDaScrewdriver.endsWith(knife)) {
			materialeProdottoDaScrewdriver += Candies.LF;
		}
		materialeProdottoDaScrewdriver = clean(
				materialeProdottoDaScrewdriver);
		String[] newFileSegmentE = materialeProdottoDaScrewdriver.split(
				knifeX);
		int howManyKnives = newFileSegmentE.length - 1;
		/* all variables with suffix R indicate material transformed
		 * according to the UTF-8 charset, or possibly that provided by
		 * the .ele file */
		String materialePreesistenteR = Equipment.oneStringUnicode_A(
				preExistent, charset);
		String materialePreesistente = Equipment.oneString(preExistent);
		/* I use the new material string twice, to create upperSegmentoE
		 * and lowerSegmentoE respectively */
		/* 1st use */
		String materiale = materialePreesistente;
		String materialeR = materialePreesistenteR;
		/* I make a convenient correction */
		if (materiale.endsWith(upper)) {
			materiale += Candies.LF;
		}
		if (materialeR.endsWith(upper)) {
			materialeR += Candies.LF;
		}
		String[] upperSegmentoE = materiale.split(upperX);
		String[] upperSegmentoRE = materialeR.split(upperX);
		/* the amount of upper does not depend on the charset */
		int quantiUpper = upperSegmentoE.length - 1;
		/* 2nd use */
		materiale = materialePreesistente;
		materialeR = materialePreesistenteR;
		/* I make a convenient correction */
		if (materiale.endsWith(lower)) {
			materiale += Candies.LF;
		}
		if (materialeR.endsWith(lower)) {
			materialeR += Candies.LF;
		}
		String[] lowerSegmentoE = materiale.split(lowerX);
		@SuppressWarnings("unused")
		String[] lowerSegmentoRE = materialeR.split(lowerX);
		/* the amount of lower does not depend on the charset */
		int quantiLower = lowerSegmentoE.length - 1;
		/* in the same way the following quantities do not depend on the
		 * charset */
		if (howManyKnives != quantiUpper) {
			throw new ExactException(
					"The file produced by Screwdriver «"
							+ nomeFileOrigine
							+ "» contains a quantity of KNIFE ("
							+ howManyKnives + ")" + Candies.LF
							+ "different from the quantity of UPPER ("
							+ quantiUpper
							+ ") that are present in the output file «"
							+ pre_existentFilename
							+ "», in the directory" + Candies.LF
							+ pre_existentPath + " .", 1106,
					"FileComponent", "");
		}
		if (howManyKnives != quantiLower) {
			throw new ExactException(
					"The file produced by Screwdriver «"
							+ nomeFileOrigine
							+ "» contains a quantity of di KNIFE ("
							+ howManyKnives + ")" + Candies.LF
							+ "different from the quantity of LOWER ("
							+ quantiLower
							+ ") that are present in the pre-existent file «"
							+ pre_existentFilename
							+ "» in the directory" + Candies.LF
							+ pre_existentPath + " .", 1107,
					"FileComponent", "");
		}
		/* control of lower-upper alternation */
		if (upperSegmentoE[0].indexOf(lower) > -1) {
			throw new ExactException("The input file «"
					+ nomeFileOrigine
					+ "» contains a wrong alternation "
					+ "of UPPER and LOWER; it starts with a LOWER.",
					1110, "FileComponent", "");
		}
		for (int i = 1; i <= quantiUpper; i++) {
			if (upperSegmentoE[i].indexOf(lower) == -1) {
				throw new ExactException("The input file «"
						+ nomeFileOrigine
						+ "» contains a wrong alternation "
						+ "of UPPER and LOWER (after the UPPER n. " + i
						+ ").", 1111, "FileComponent", "");
			}
		}
		if (lowerSegmentoE[lowerSegmentoE.length - 1].indexOf(
				upper) > -1) {
			throw new ExactException("The input file «"
					+ nomeFileOrigine
					+ "» contains a wrong alternation "
					+ "of UPPER and LOWER; it ends with an UPPER.",
					1112, "FileComponent", "");
		}
		for (int i = 0; i < quantiLower; i++) {
			if (lowerSegmentoE[i].indexOf(upper) == -1) {
				throw new ExactException("The input file «"
						+ nomeFileOrigine
						+ "» contains a wrong alternation "
						+ "of UPPER and LOWER (before the LOWER n. " + i
						+ ").", 1113, "FileComponent", "");
			}
		}
		/* now we are sure that quantiUpper, quantiLower and quantiKnife
		 * indicate the same quantity */
		String[] oldFileSegmentE = new String[quantiUpper + 1];
		String[] oldFileSegmentRE = new String[quantiUpper + 1];
		/* containedE is the list of texts contained between a UPPER and
		 * a LOWER, therefore 1 less than the segments that are
		 * intermediate between the various upper-lower pairs; it is
		 * necessary to count the first and the last */
		/* remember that upperSegmentoE is the list of segments
		 * resulting from the split based on the upper only */
		/* for the old content we also refer to the text transformed
		 * according to the charset, so we calculate both with R and
		 * without R, but what will be really used is the one with R */
		String[] vecchioContenutoRE = new String[quantiUpper];
		String[] vecchioContenutoE = new String[quantiUpper];
		int k = 0;
		for (int j = 0; j < quantiUpper + 1; j++) {
			if (j == 0) {
				oldFileSegmentE[j] = upperSegmentoE[j];
				oldFileSegmentRE[j] = upperSegmentoRE[j];
			} else {
				k = upperSegmentoE[j].indexOf(lower);
				oldFileSegmentE[j] = upperSegmentoE[j].substring(k
						+ lower.length());
				vecchioContenutoE[j - 1] = upperSegmentoE[j].substring(
						0, k);
				k = upperSegmentoRE[j].indexOf(lower);
				oldFileSegmentRE[j] = upperSegmentoRE[j].substring(k
						+ lower.length());
				vecchioContenutoRE[j - 1] = upperSegmentoRE[j]
						.substring(0, k);
			}
			oldFileSegmentRE[j] = clean(oldFileSegmentRE[j]);
		}
		/* I remove any line-feeds in the queue */
		oldFileSegmentE[quantiUpper] = equalize(
				oldFileSegmentE[quantiUpper]);
		oldFileSegmentRE[quantiUpper] = equalize(
				oldFileSegmentRE[quantiUpper]);
		/* CURRENT SITUATION OF THE PRE-EXISTING MATERIAL */
		/* I make an example of a file that contains 2 upper-lower
		 * pairs; we have: oldSegmentE [0], oldContentsE [0],
		 * oldSegmentE [1], oldContentsE [1], oldSegmentE [2] */
		/* note that the distinction R and not R are not necessary for
		 * new text */
		newFileSegmentE[quantiUpper] = equalize(
				newFileSegmentE[quantiUpper]);
		boolean noQuestion = false;
		k = 0;
		/* now I compare each of the new segments with the old ones; the
		 * cycle continues until diversity is encountered */
		/* note that the comparison is made exclusively on the R
		 * version, that is, the text transformed according to the
		 * charset */
		for (; k < quantiUpper + 1; k++) {
			String nuovo = newFileSegmentE[k];
			String vecchio = oldFileSegmentE[k];
			String vecchioR = oldFileSegmentRE[k];
			/* this if is set to save time in case it is not necessary
			 * to compact; could be removed */
			if (nuovo.equals(vecchioR) | nuovo.equals(vecchio)) {
				continue;
			}
			nuovo = Strings.compatta_B(nuovo);
			vecchio = Strings.compatta_B(vecchio);
			vecchioR = Strings.compatta_B(vecchioR);
			if (nuovo.equals(vecchioR) | nuovo.equals(vecchio)) {
				continue;
			}
			/* it's not a java file, skip all import processing */
			if (!type.equals("java")) {
				break;
			}

			// 3 SECTORS EACH SEGMENTS
			String coda = null;
			int fineImport = 0;
			/* the 3 sectors are: 1) before imports, i.e. comments line
			 * and package; 2) import lines; 3) after imports, i.e.
			 * ordinary java code */
			String[] newFileSectorE = new String[3];
			String[] oldFileSectorE = new String[3];
			String[] oldFileSectorRE = new String[3];
			String[] newFileSectorXE = newFileSegmentE[k].split(
					"\\n\\x20*import ");
			String[] oldFileSectorXE = oldFileSegmentE[k].split(
					"\\n\\x20*import ");
			String[] oldFileSectorRXE = oldFileSegmentRE[k].split(
					"\\n\\x20*import ");
			newFileSectorE[0] = newFileSectorXE[0];
			coda = newFileSectorXE[newFileSectorXE.length - 1];
			/* 59 is the semicolon */
			fineImport = coda.indexOf(59);
			/* the +1 is used to go beyond the LINE FEED after the
			 * semicolon */
			newFileSectorE[2] = coda.substring(fineImport + 1);

			/* without R */
			oldFileSectorE[0] = oldFileSectorXE[0];
			coda = oldFileSectorXE[oldFileSectorXE.length - 1];
			/* 59 is the semicolon */
			fineImport = coda.indexOf(59);
			/* the +1 is used to go beyond the LINE FEED after the
			 * semicolon */
			oldFileSectorE[2] = coda.substring(fineImport + 1);

			/* with R */
			oldFileSectorRE[0] = oldFileSectorRXE[0];
			coda = oldFileSectorRXE[oldFileSectorRXE.length - 1];
			/* 59 is the semicolon */
			fineImport = coda.indexOf(59);
			/* the +1 is used to go beyond the LINE FEED after the
			 * semicolon */
			oldFileSectorRE[2] = coda.substring(fineImport + 1);

			// IMPORT PROCESSING

			/* since no import is assumed to have an ASCII character>
			 * 127, the distinction between "without R" and "with R" is
			 * not necessary */

			List<String> nuovoImportE = new ArrayList<String>();
			// List <String> vecchioImportE = new ArrayList <String> ();
			List<String> vecchioImportRE = new ArrayList<String>();
			/* oldImportE and newImportE are real and clean imports from
			 * the word import and semicolon */
			for (int i = 0; i < newFileSectorXE.length - 1; i++) {
				/* 59 is the semicolon */
				/* the +1 is to skip the first line, which declares the
				 * package */
				int j = newFileSectorXE[i + 1].indexOf(59);
				nuovoImportE.add(newFileSectorXE[i + 1].substring(0, j)
						.trim());
			}

			/* 2 separate for loops for "without R" and "with R" */
			/* without R */
			// for (int i = 0; i <sectorVecchioXE.length - 1; i ++) {
			/* 59 is the semicolon */
			/* +1 is to skip the first line, which declares ilò //
			 * package */
			// int j = sector Old XE [i + 1] .indexOf (59);
			// oldImportE.add (sectorOldXE [i + 1] .substring (0,
			// j) .trim ());
			// }
			/* with R */
			for (int i = 0; i < oldFileSectorRXE.length - 1; i++) {
				/* 59 is the semicolon */
				/* the +1 is to skip the first line, which declares the
				 * package */
				int j = oldFileSectorRXE[i + 1].indexOf(59);
				vecchioImportRE.add(oldFileSectorRXE[i + 1].substring(0,
						j).trim());
			}

			/* control not identical; if the presence of 2 identical
			 * ones were verified, the following algorithm would fail */
			searchForRepetion(nuovoImportE, nomeFileOrigine, false);

			/* 2 separate for loops for "without R" and "with R" */
			/* with R */
			searchForRepetion(vecchioImportRE, pre_existentFilename,
					true);

			/* now oldImportE and newImportE are clean, ready for use */
			oldFileSectorE[1] = "";
			oldFileSectorRE[1] = "";

			/* 2 separate for loops for "without R" and "with R" */
			/* with R */
			for (int iv = 0; iv < vecchioImportRE.size(); iv++) {
				oldFileSectorRE[1] += "import " + vecchioImportRE.get(
						iv) + ";" + Candies.LF;
			}

			/* the saved imports are those that the developer has typed
			 * later, and therefore he does not want to lose in a
			 * reworking of Screwdriver */
			List<String> salvatiE = new ArrayList<String>();
			/* now I try if each of the old imports (therefore
			 * potentially typed by the developer after the first
			 * creation) is present or not from the source code produced
			 * by Screwdriver */

			/* for this for loop, since we are going to read the
			 * contents of the imports and compare them, I assume that I
			 * can run only once, with the R mode, and then correctly
			 * save them. */
			for (int iv = 0; iv < vecchioImportRE.size(); iv++) {
				String s = vecchioImportRE.get(iv);
				int in = 0;
				for (; in < nuovoImportE.size(); in++) {
					if (s.equals(nuovoImportE.get(in))) {
						break;
					}
				}
				/* if the import is not present among those of this
				 * processing, this means that it has been entered by
				 * hand ... */
				if (in == nuovoImportE.size()) {
					/* ... therefore I have to save it, and I memorize
					 * it by writing down w, which is the position of
					 * the last import that coincides instead */
					/* w could be -1 */
					salvatiE.add(s);
				}
			}
			for (int is = 0; is < salvatiE.size(); is++) {
				nuovoImportE.add(salvatiE.get(is));
			}
			newFileSectorE[1] = "";
			for (int iv = 0; iv < nuovoImportE.size(); iv++) {
				newFileSectorE[1] += "import " + nuovoImportE.get(iv)
						+ ";" + Candies.LF;
			}
			/* the 3 sectors are: 1) before imports, i.e. comments line
			 * and package; 2) import lines; 3) after imports, i.e.
			 * ordinary java code */
			Boolean[] comparison = new Boolean[3];
			for (int i = 0; i < 3; i++) {
				comparison[i] = Strings.compatta_B(newFileSectorE[i])
						.equals(Strings.compatta_B(oldFileSectorRE[i]));
			}
			/* if the only difference is the added imports, there is no
			 * need to ask for permission */
			if (comparison[0] & comparison[1] & comparison[2]) {
				continue;
			}
			newFileSegmentE[k] = newFileSectorE[0] + newFileSectorE[1]
					+ newFileSectorE[2];
			/* no question if only imports are different */
			noQuestion = comparison[0] & comparison[2];
			break;
		}
		/* if I find one, the k-th segment, different, then I have to
		 * trigger the request for permission to overwrite */
		if (k < quantiUpper + 1) {
			/* I put the first piece ... */
			String cumulo = newFileSegmentE[0];
			/* ... and then the following */
			for (int n = 1; n < quantiUpper + 1; n++) {
				cumulo += upper;
				cumulo += vecchioContenutoRE[n - 1];
				cumulo += lower;
				cumulo += newFileSegmentE[n];
			}
			/* I call him arrogant when, despite the need to make a
			 * replacement, he does not ask for any permission */
			/* he is humble, because he is not arrogant, if the last
			 * argument is false; for now there are no other uses of
			 * humble with arrogant = true */
			finishLine(cumulo, pre_existentFilename, nomeFileOrigine,
					recycleBinY, preExistent, candies, noQuestion);
		}
	}

	/** @param noQuestion false if I asks for permission before
	 *        acting */
	private void finishLine(final String materialeOutput,
			final String nomeFileOutput, final String nomeFileInput,
			final String recycleBinY, File output, CandyScrew candies,
			final boolean noQuestion)

			throws ExactException {

		/* freeze files are those that must not be touched at all, they
		 * are mentioned in the external properties file */
		if (!noQuestion & !remember) {
			boolean freeze = false;
			boolean freezeDue = false;
			wellIPermit = false;
			if (candies.freezeE != null) {
				int i = 0;
				for (; i < candies.freezeE.size(); i++) {
					if (candies.freezeE.get(i).equalsIgnoreCase(
							nomeFileOutput)) {
						break;
					}
				}
				freeze = i < candies.freezeE.size();
			}
			/* could become freeze by looking in the other list */
			if (!freeze & candies.freezeDueE != null) {
				int j = 0;
				for (; j < candies.freezeDueE.size(); j++) {
					if (candies.freezeDueE.get(j).equalsIgnoreCase(
							nomeFileOutput)) {
						break;
					}
				}
				freezeDue = j < candies.freezeDueE.size();
			}
			if (!freeze & !freezeDue) {
				String question = "The file " + Mix.dress_A(
						nomeFileOutput)
						+ " has changed, can I overwrite it?";
				logger.info(question);
				/* the "Yes" button is locked only if I have declared
				 * some files as "freezeDue" and I have declared that
				 * the java source is not inside, that is, it is not
				 * written from java code already present in the ele
				 * file */
				boolean lockButtonYes = false;
				Remember noMore = new Remember(null, question,
						"Question", lockButtonYes);
				logger.info(noMore.answer[0] ? "Yes"
						: freeze ? "Mandatory NO" : "No");
				wellIPermit = noMore.answer[0];
				remember = noMore.answer[1];
			} else if (freezeDue) {
				logger.info("So, I do not change the file " + Mix
						.dress_A(nomeFileOutput) + ".");
			}
		}
		if (wellIPermit) {
			String x = Skill.datePosition(recycleBinY);
			File destiny = new File(x + nomeFileInput);
			destiny.delete();
			output.renameTo(destiny);
			Equipment.writeFileFromOneStringUnicode_A(output,
					materialeOutput, "UTF-8");
		}
	}

	private static void searchForRepetion(List<String> stringE,
			final String fileName, final boolean old)
			throws ExactException {
		for (int i = 0; i < stringE.size(); i++) {
			String s = stringE.get(i);
			int j = i + 1;
			for (; j < stringE.size(); j++) {
				if (s.equals(stringE.get(j))) {
					break;
				}
			}
			if (j < stringE.size()) {
				ExactException ce = new ExactException(
						"There are 2 identical imports in the " + (old
								? "old "
								: "new ") + Mix.dress_A(fileName) + ": "
								+ s, 1116, "FileComponent", "");
				throw ce;
			}
		}
	}

	/* in producing the files within the algorithms of the program, LFs
	 * can be created more or less at the end of the file, which cause a
	 * "different" result in the comparison of the sources, and
	 * therefore a rewriting; to avoid this, I proceed to a draw of the
	 * LF in the queue */
	private static String equalize(final String s0) {
		String s = s0;
		/* I remove any line feed in the queue */
		while (s.endsWith(Candies.LF)) {
			s = s.substring(0, s.length() - 1);
		}
		/* I replace only one */
		s += Candies.LF;
		s = s.replaceAll("\\r\\n", Candies.LF);
		s = s.replaceAll("\\n\\r", Candies.LF);
		return s;
	}

	private static String clean(final String s0) {
		String s = s0;
		s = s.replaceAll("\\r", "");
		return s;
	}

	/**
	 * <p>
	 * Creation date: 2020-09-09<br>
	 * Last updated: 2020-09-09<br>
	 * Class: Skill
	 * 
	 * @author Massimo Maglioni
	 *         <p>
	 *         Description:
	 *         </p>
	 * @param y directory name where a date has to be added
	 * @return the directory name followed by today date */
	public static String datePosition(final String y) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String x = sdf.format(new Date());
		File d = new File(Mix.dress_C(y) + x);
		if (d.exists() & !d.isDirectory()) {
			d.delete();
		}
		if (!d.exists()) {
			d.mkdir();
		}
		return d.getPath() + sep;
	}
}