//
// 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.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import it.ramecera.salad.everyday.Candies;
import it.ramecera.salad.everyday.ExactException;
import it.ramecera.salad.everyday.Mix;
import it.ramecera.salad.graphic.Placard;

/**
 * <p>
 * Application to automatically generate skeletons of a Maven
 * application.
 * </p>
 * 
 * @author M. Maglioni
 *         <p>
 *         ​​Company: Ramecera™<br>
 *         Creation date: 2020-04-09<br>
 *         Last updated: 2020-08-20<br>
 *         </p>
 */
final public class Hammer {

	private static ExactException ne = new ExactException();

	// CONSTANTS

	static boolean allRight;

	/** ordinary logger */
	private static final Logger logger = Logger.getLogger(Hammer.class);

	/**
	 * <p>
	 * Simple main method.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-08-20<br>
	 * </p>
	 * <p>
	 * History: 2020-08-02 implementation of N13 (see
	 * martoraProject.ods)
	 * </p>
	 * 
	 * @param args null
	 * @throws ExactException exception specified by a numerical code */
	public static void main(String[] args)

			throws ExactException {

		/** the types of markups are:<br>
		 * 1 = a date, mandatory<br>
		 * 2 = an unsigned non-negative integer, mandatory<br>
		 * 3 = a string of at least 1 character, mandatory<br>
		 * 4 = no parameters<br>
		 * 5 = a version of a software, for example 1.3.13.RELEASE
		 * N6<br>
		 * 6 = a string, optional<br>
		 * 7 = a CSS color, of the type #ffffff or rgb ( 255,255,255) or
		 * white<br>
		 * 8 = like 12, and automatically converted to lower case<br>
		 * 9 = like 4, but to look for among it includes<br>
		 * 10 = like 3, but to look for among includes<br>
		 * 11 = like 5, but to be found among the includes<br>
		 * 12 = like 3 but composed of a single word<br>
		 * 13 = like 12 but with no more than one slash: example :
		 * "security / user.jsp", and at least one character after the
		 * slash<br>
		 * 14 = like 13 but optional, and if there is no data, the one
		 * of the previous markup is taken<br>
		 * 15 = an integer with or without sign, mandatory<br>
		 * 16 = like 12 but optional<br>
		 * occurrences are:<br>
		 * 17 = a string composed of words separated by commas,
		 * mandatory<br>
		 * 18 = a string consisting of a select SQL, mandatory<br>
		 * 19 = a string, mandatory one of the values ​​declared in the
		 * "domain" column<br>
		 * 20 = precedes the text of a file or of a source code<br>
		 * 21 = like 19, but to be searched among the includes<br>
		 * 22 = like 17, but optional<br>
		 * 23 = a language code , ISO 639-1<br>
		 * 24 = like 17, but substrings must be composed by one word *
		 * presence = 0: none or as many as you want<br>
		 * presence = 1: one and only one<br>
		 * presence = 2: 1 or none<br>
		 * presence = 3: at least 1<br>
		 * presence = 4: none or as many as you want, but without
		 * identical repetitions<br>
		 * presence = 5: at least 1, but without identical repetitions
		 * <br>
		 * Atoms, taken at 5 to 5, they go to form the markups. */
		/* @formatter:off */
		String[][] atomi = {
				{ "antisamy", "4", "2", "", "", "", "", "" },
				{ "appse", "3", "1", "", "", "", "", "" },
				{ "arraystring", "3", "3", "+jsp", "", "", "", "" },
				{ "bdefmenu", "8", "4", "indexjsp", "", "bfixedtop", "", "" },
				{ "belong", "3", "0", "+jsp", "", "", "", "" },
				{ "bfixedtop", "4", "0", "+bdefmenu", "", "", "", "" },
				{ "blabel", "3", "0", "bdefmenu", "burl", "", "", "" },
				{ "blank", "4", "0", "+jsp", "", "", "", "" },
				{ "bmenu", "8", "0", "+jsp, +indexjsp, +userpass", "", "", "", "" },
				{ "boolean", "3", "3", "+jsp", "", "", "", "" },
				{ "burl", "12", "3", "+blabel", "", "", "", "" },
				{ "captc", "3", "2", "", "", "", "", "" },
				{ "charset", "3", "2", "", "", "", "", "" },
				{ "colorform", "7", "2", "userpass", "", "", "", "" },
				{ "crud", "4", "0", "+jsp", "", "", "", "" },
				{ "cssclass", "12", "4", "+text,+jsp", "", "", "", "" },
				{ "dao", "24", "0", "+method, +formn", "", "", "", "" },
				{ "defaulan", "23", "2", "", "", "", "", "" },
				{ "depen", "2", "1", "", "", "", "", "" },
				{ "dress", "12", "0", "+jsp", "", "", "", "" },
				{ "edefn", "14", "0", "", "", "", "", "" },
				{ "ev", "5", "2", "", "", "", "", "" },
				{ "fcartel", "3", "0", "+formn", "", "", "", "" },
				{ "file", "20", "4", "", "", "", "", "" },
				{ "filte", "4", "2", "", "", "", "", "" },
				{ "company", "3", "1", "", "", "", "", "" },
				{ "flabel", "3", "0", "+formt,+formn,+forma,+formc,+formr", "", "", "", "" },
				{ "forma", "3", "0", "jsp", "flabel", "", "", "forma, formc, formt, formn, formr, jsp, valcons" },
				{ "formc", "3", "0", "jsp", "flabel", "", "", "forma, formc, formt, formn, formr, jsp, valcons" },
				{ "formn", "3", "0", "jsp", "flabel, fcartel", "mybutton, dao, hsqln, ftokens", "", "forma, formc, formt, formn, formr, jsp, valcons" },
				{ "formr", "3", "0", "jsp", "ftokens", "flabel, fstart", "", "forma, formc, formt,formn, formr, jsp, valcons" },
				{ "formt", "3", "0", "jsp", "flabel", "", "", "forma, formc, formt,formn, formr, jsp, valcons" },
				{ "fstart", "3", "0", "+formr", "", "", "", "" },
				{ "ftokens", "17", "0", "+formn,+formr", "", "", "", "" },
				{ "goal", "13", "3", "+requmap", "", "", "", "" },
				{ "hdbms", "19", "0", "+hdefrail", "", "", "DB2, MySQL, Oracle, Oracle8i, Postgres", "" },
				{ "hdbschema", "8", "4", "+hdefrail", "", "", "", "" },
				{ "hdefrail", "19", "0", "", "hdbschema, hdbms",
						"hjndi, hjarv", "0,1,2,3,4,5,6,7,8,9", "" },
				/* FUTURE RELEASE N6 */
//				{ "hddl", "17", "2", "", "", "", "", "" },
//				{ "hembedded", "4", "2", "", "", "", "", "" },
				{ "hjarv", "5", "3", "+hdefrail", "", "", "", "" },
				{ "hjndi", "12", "0", "+hdefrail", "", "", "", "" },
				{ "hjpav", "19", "1", "+hv", "", "", "1,2", "", "" },
				{ "hrail", "2", "0", "+utabuser, +qjobname", "", "", "", "" },
				{ "hsqln", "18", "0", "+formn", "", "", "", "" },
				{ "hv", "5", "2", "", "hjpav", "", "", "" },
				{ "hvalid", "5", "2", "!svalid", "", "", "", "" },
				{ "i18n", "3", "2", "sinterce", "", "", "", "" },
				{ "indexjsp", "4", "2", "", "", "bmenu, ooptioncolor, ooptionhover, ooptbackcol1, ooptbackcol2", "", "" },
				{ "integer", "3", "3", "+jsp", "", "", "", "" },
				{ "jacksonver", "3", "2", "", "", "", "", "" },
				{ "jeev", "5", "2", "", "", "", "", "" },
				{ "jsp", "13", "4", "", "belong",
						"bmenu, string, arraystring, integer, long, boolean, dress, cssclass, refresh, pagetitle, crud, blank, legend", "", "" },
				{ "language", "23", "0", "i18n", "", "", "", "" },
				{ "legend", "3", "0", "+jsp", "", "", "", "" },
				{ "log4j", "5", "2", "", "", "", "", "" },
				{ "long", "3", "3", "+jsp", "", "", "", "" },
				{ "matrix", "4", "2", "", "", "", "", "" },
				{ "mavbu", "4", "2", "mavcl, mavwa, mavcp", "", "", "", "" },
				{ "mavcl", "5", "2", "mavbu, mavwa, mavcp", "", "", "", "" },
				{ "mavco", "5", "1", "", "", "", "", "" },
				{ "mavcp", "5", "2", "mavbu, mavwa, mavcl", "", "", "", "" },
				{ "mavgr", "3", "1", "", "", "", "", "" },
				{ "mavmo", "5", "1", "", "", "", "", "" },
				{ "mavwa", "5", "2", "mavbu, mavcp, mavcl", "", "", "", "" },
				{ "method", "20", "4", "", "", "", "", "" },
				{ "model", "4", "3", "+requmap", "", "", "", "" },
				{ "mv", "5", "1", "", "", "", "", "" },
				{ "mybutton", "3", "0", "+formn, +formt, +forma", "", "", "", "" },
				{ "oalign", "19", "3", "+odefcss", "", "", "left, center, right", "" },
				{ "odefcss", "12", "4", "", "", "", "", "" },
				{ "ooptbackcol1", "7", "0", "+indexjsp", "", "", "", "" },
				{ "ooptbackcol2", "7", "0", "+indexjsp", "", "", "", "" },
				{ "obackcolor", "7", "3", "+odefcss", "", "", "", "" },
				{ "ocolor", "7", "3", "+odefcss", "", "", "", "" },
				{ "ofontsize", "15", "3", "+odefcss", "", "", "", "" },
				{ "omargin", "15", "3", "+odefcss", "", "", "", "" },
				{ "ooptioncolor", "7", "0", "+indexjsp", "", "", "", "" },
				{ "ooptionhover", "7", "0", "+indexjsp", "", "", "", "" },
				{ "opadding", "15", "3", "+odefcss", "", "", "", "" },
				{ "others", "24", "0", "+method", "", "", "", "" },
				{ "pagetitle", "3", "0", "+jsp", "", "", "", "" },
				{ "permit", "19", "0", "+requmap", "", "", "all, user, admin", "" },
				{ "pompr", "2", "2", "", "", "", "", "" },
				{ "pragma", "4", "2", "jsp", "", "", "", "" },
				{ "pretprint", "4", "2", "sv+3.2.0", "", "", "", "" },
				{ "primary", "10", "2", "", "", "", "", "" },
				{ "qcron", "3", "2", "+qjobname", "", "", "", "" },
				{ "qjobname", "12", "0", "quartz", "hrail", "qcron, qsimple", "", "" },
				{ "quartz", "5", "2", "qjobname", "", "", "", "" },
				{ "qsimple", "3", "2", "+qjobname", "", "", "", "" },
				{ "redirect", "3", "0", "+requmap", "", "", "", "" },
				{ "refresh", "2", "0", "+jsp", "", "", "", "" },
				{ "requmap", "12", "0", "jsp", "", "model, permit, goal, redirect", "", "" },
				{ "sdefauto", "19", "2", "", "", "", "no, byname, bytype, autodetect, constructor", "" },
				{ "sieco", "14", "0", "", "", "", "", "" },
				{ "sinterce", "12", "0", "", "", "", "", "" },
				{ "uintp", "12", "0", "uv", "", "", "", "" },
				{ "sreso", "16", "4", "", "", "", "", "" },
				{ "srobo", "4", "2", "", "", "", "", "" },
				{ "string", "3", "3", "+jsp", "", "", "", "" },
				{ "sv", "5", "1", "primary", "", "", "", "" },
				{ "svalid", "4", "2", "!hvalid", "", "", "", "" },
				{ "text", "3", "2", "indexjsp", "cssclass", "", "", "" },
				{ "upassword", "12", "2", "+utabuser", "", "", "", "" },
				{ "userpass", "21", "2", "uv", "", "bmenu",
						"simple, domain, trivial", "" },
				{ "uspaformadmin", "3", "2", "userpass+trivial", "", "", "", "" },
				{ "uspaformuser", "3", "2", "userpass+trivial", "", "", "", "" },
				{ "usignup", "4", "2", "userpass", "", "", "", "" },
				{ "utabuser", "12", "2", "userpass",
						"hrail, uwelcome, upassword", "", "", "" },
				{ "uv", "5", "2", "sv, xprovider", "", "", "", "" },
				{ "uwelcome", "12", "2", "+utabuser", "", "", "", "" },
				{ "valcons", "19", "0", "defaulan", "valtag", "valparams", "@AssertFalse, @AssertFalse.List, @AssertTrue, @AssertTrue.List, @DecimalMax, @DecimalMax.List, @DecimalMin, @DecimalMin.List, @Digits, @Digits.List, @Future, @Future.List, @Max, @Max.List, @Min, @Min.List, @NotEmpty, @NotNull, @NotNull.List, @Null, @Null.List, @Past, @Past.List, @Pattern, @Pattern.List, @Size, @Size.List", "formt, forma, formc, valcons" },
				{ "vallabel", "3", "0", "defaulan", "valmess", "vallang", "", "" },
				{ "vallang", "23", "0", "+vallabel", "", "", "", "" },
				{ "valmess", "3", "0", "+vallabel", "", "", "", "" },
				{ "valparams", "3", "0", "+valcons", "", "", "", "" },
				{ "valtag", "3", "0", "+valcons", "", "", "", "" },
				{ "weberror", "4", "2", "", "", "", "", "" },
				{ "webmime", "4", "2", "", "", "", "", "" },
				{ "wparams", "3", "0", "", "", "", "", "" },
				{ "wv", "5", "2", "", "", "", "", "" },
				{ "xauth", "18", "2", "xprovider+jdbc, !xgbac", "", "", "", "" },
				{ "xencoder", "19", "2", "uv", "", "", "useridmd5, saltedsha256", "" },
				{ "xlbase", "12", "2", "xprovider+ldap", "", "", "", "" },
				{ "xgbac", "18", "2", "xprovider+jdbc, !xauth, !xusers", "",
						"", "", "" },
				{ "xlpass", "12", "2", "xprovider+ldap", "", "", "", "" },
				{ "xlclass", "3", "2", "xprovider+ldap", "", "", "", "" },
				{ "xlservice", "4", "2", "xprovider", "", "", "", "" },
				{ "xprovider", "19", "2", "uv", "", "",
						"user-service, class, jdbc, ldap", "" },
				{ "xusers", "18", "2", "xprovider+jdbc, !xgbac", "", "", "", "" } };

		/* @formatter:on */
		PropertyConfigurator.configure("log4j.properties");

		// READING PROPERTIES

		if (args.length == 0) {
			new Placard(null, "An argument is missing at the"
					+ " start of the main method.");
			return;
		}
		String message = "Start of process";
		logger.info(Candies.LF + Candies.LF
				+ "==========================================="
				+ Candies.LF + message + Candies.LF
				+ "===========================================");
		CandyScrew candyScrew = new CandyScrew();
		candyScrew.appName = args[0];
		if (!candyScrew.appName.matches("\\p{Alpha}\\p{Graph}*")) {
			Mix.discloseError("The application name " + Mix.dress_A(
					candyScrew.appName) + " is incorrect.", "Stop",
					logger);
			return;
		}
		candyScrew.ele = candyScrew.appName + ".ele";
		try {
			candyScrew.readProperties(candyScrew.appName);
			logger.trace(candyScrew.toString());
			logger.info(Candies.LF + Cst.CUT0 + "ELEMENTARY FILE: "
					+ candyScrew.appName + Candies.LF + Cst.CUT0);
		} catch (ExactException e) {
			Mix.discloseError(
					"Reading the properties, an error was found." + e
							.getMessage(), "Stop", logger);
			return;
		}

		// IMPLEMENTATION OF THE LIST OF MARKUPS

		try {
			// I instantiate the markups array
			HashMap<String, Markup> markupE = markupFactory(atomi);
			Collection<Markup> valueMarkupE = markupE.values();
			supposedMarkupsCheck(valueMarkupE.iterator(), markupE);
			precedingOnesControl(valueMarkupE.iterator(), markupE);
			logger.trace(markupE_toString(markupE));
			ElementaryFile elementaryFile = new ElementaryFile(markupE,
					candyScrew);
			elementaryFile.appName = candyScrew.appName;
			/* we perform the transformation from ELE file to the trains
			 * structure */
			elementaryFile.trainFactory(candyScrew.inputYS,
					candyScrew.ele, candyScrew.includeYS);
			/* now I have the list of markups (and trains, therefore of
			 * occurrence), I scroll it to check the attendance */
			elementaryFile.controlloPresenze();
			/* checking the validity of a tape based on the version of a
			 * certain software */
			elementaryFile.substantialChecks();

			// CONVERT

			/* the "convert" method turns trains into a maven / spring
			 * web app; remember that the elementary object is the input
			 * file */

			elementaryFile.convert();

			allRight = true;
			message = "Process ending.";
		} catch (ExactException e) {
			message = "";
			if (e.className != null) {
				message += "Class: " + e.className + Candies.LF;
			}
			if (e.method != null) {
				message += "Method: " + e.method + Candies.LF;
			}
			if (e.datum != null) {
				message += Candies.LF + e.datum;
			}
			logger.error(message);
			new Placard(null, message, "Error code " + e.code);
			message = "Process ending NO OK.";
		} catch (FileNotFoundException e) {
			ExactException ne = new ExactException();
			ne.datum = e.getMessage();
			ne.code = 1500;
			logger.error(ne.datum);
			new Placard(null, ne.datum, "Error code " + ne.code);
			message = "Process ending NO OK.";
		} catch (IOException e) {
			e.printStackTrace();
		}
		Mix.discloseInfo(message, "Notice", logger);
	}

	/**
	 * <p>
	 * Classic toString method, other than the fact that it is static.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09<br>
	 * </p>
	 * 
	 * @param mE list of markups
	 * @return the compound string */
	public static String markupE_toString(HashMap<String, Markup> mE) {
		String s = "";
		s += Candies.LF + Candies.LF + Candies.LF + Candies.LF;
		s += Cst.CUT0;
		s += "ELENCO DEI MARKUP E DEI LORO PRESUPPOSTI" + Candies.LF;
		s += Cst.CUT0;
		Collection<Markup> valueMarkupE = mE.values();
		Iterator<Markup> iteratorMarkup = valueMarkupE.iterator();
		while (iteratorMarkup.hasNext()) {
			Markup m = iteratorMarkup.next();
			s += Cst.CUT0;
			s += "stub = " + m.stub;
			s += "; p = " + m.p;
			s += "; presenza = " + m.presenza;
			if (m.mandatoryWagE != null) {
				s += "; obbligatori = ";
				for (String t : m.mandatoryWagE) {
					s += t + ", ";
				}
				/* I cut the last 2 characters: "," */
				s = s.substring(0, s.length() - 2);
			}
			if (m.optionalWagE != null) {
				s += "; facoltativi = ";
				for (String t : m.optionalWagE) {
					s += t + ", ";
				}
				/* I cut the last 2 characters: "," */
				s = s.substring(0, s.length() - 2);
			}
			if (m.wagon) {
				s += "; it is a wagon" + Candies.LF;
			}
			s += Candies.LF;
			if (m.implyE != null && m.implyE.length > 0) {
				for (int i = 0; i < m.implyE.length; i++) {
					Imply p = m.implyE[i];
					s += p.toString(i);
				}
			}
			if (m.recurrenceE.size() > 0) {
				s += "          reciurrences list, quantity "
						+ m.recurrenceE.size() + Candies.LF;
				for (int i = 0; i < m.recurrenceE.size(); i++) {
					s += Cst.CUT2;
					s += "          Recurrence " + i + Candies.LF;
					s += "          " + m.recurrenceE.get(i).locomotor
							.toString(0, mE);
					Collection<Wagon> valueWagonE = m.recurrenceE.get(
							i).wagonE.values();
					Iterator<Wagon> iteratorWagon = valueWagonE
							.iterator();
					int j = 1;
					while (iteratorWagon.hasNext()) {
						Wagon wagon = iteratorWagon.next();
						s += "          " + wagon.toString(j, mE);
						j++;
					}
				}
			}
		}
		s += Candies.LF;
		return s;
	}

	private static HashMap<String, Markup> markupFactory(
			String[][] atomi)

			throws ExactException {

		HashMap<String, Markup> markupE = new HashMap<String, Markup>();
		for (int i = 0; i < atomi.length; i++) {
			Markup markup = new Markup();
			markup.markupFactory(atomi, i);
			if (markupE.containsKey(markup.stub)) {
				ne.datum = "The markup " + Mix.dress_A(markup.stub)
						+ " it is repeated in the markup definition table.";
				ne.code = 1502;
				throw ne;
			}
			markupE.put(markup.stub, markup);
		}
		return markupE;
	}

	private static void supposedMarkupsCheck(Iterator<Markup> iterator,
			HashMap<String, Markup> markupE)

			throws ExactException {

		while (iterator.hasNext()) {
			Markup m = iterator.next();
			/* if the assumption markup declaration is present ... */
			if (m.implyE != null) {
				for (int n = 0; n < m.implyE.length; n++) {
					if (!m.implyE[n].stub.equals("")) {
						if (!markupE.containsKey(m.implyE[n].stub)) {
							ne.datum = "The markup " + Mix.dress_A(
									m.implyE[n].stub) + ", supposed by "
									+ Mix.dress_A(m.stub)
									+ ", does not exist.";
							ne.code = 1501;
							throw ne;
						} else if (m.implyE[n].isWagon) {
							markupE.get(m.implyE[n].stub).wagon = false;
							markupE.get(m.stub).wagon = true;
						}
					}
				}
			}
			/* the following 2 checks verify the accuracy of the
			 * definition of the atoms, and regardless of what will then
			 * be written in the .ele file */
			if (m.mandatoryWagE != null) {
				controlloObbligatori(markupE, m);
			}
			if (m.optionalWagE != null) {
				controlloFacoltativi(markupE, m);
			}
		}
	}

	/**
	 * <p>
	 * Check the validity of the list of previous markups.
	 * </p>
	 * 
	 * @author M. Maglioni
	 *         <p>
	 *         ​​Company: Ramecera™<br>
	 *         Creation date: 2020-04-09<br>
	 *         Last updated: 2020-04-09<br>
	 *         </p>
	 */

	private static void precedingOnesControl(Iterator<Markup> iterator,
			HashMap<String, Markup> markupE)

			throws ExactException {

		while (iterator.hasNext()) {
			Markup m = iterator.next();
			/* if the assumption markup declaration is present ... */
			if (m.precedingE != null) {
				for (int n = 0; n < m.precedingE.length; n++) {
					if (!markupE.containsKey(m.precedingE[n])) {
						ne.datum = "The markup " + Mix.dress_A(
								m.precedingE[n])
								+ ", declared as previous by «" + Mix
										.dress_A(m.stub)
								+ ", does not exist.";
						ne.code = 1506;
						throw ne;
					}
				}
			}
		}
	}

	private static void controlloFacoltativi(
			HashMap<String, Markup> markupE, Markup m)

			throws ExactException {

		for (int j = 0; j < m.optionalWagE.length; j++) {
			if (!markupE.containsKey(m.optionalWagE[j])) {
				ne.datum = "The markup " + Mix.dress_A(
						m.optionalWagE[j]) + ", optional for " + Mix
								.dress_A(m.stub) + ", does not exist.";
				ne.code = 1504;
				throw ne;
			} else if (m.mandatoryWagE != null) {
				for (int j1 = 0; j1 < m.mandatoryWagE.length; j1++) {
					if (m.optionalWagE[j].equals(m.mandatoryWagE[j1])) {
						ne.datum = "The markup " + Mix.dress_A(
								m.optionalWagE[j])
								+ ", cannot be both optional and mandatory.";
						ne.code = 1505;
						throw ne;
					}
				}
			}
		}
	}

	private static void controlloObbligatori(
			HashMap<String, Markup> markupE, Markup m)

			throws ExactException {

		for (int j = 0; j < m.mandatoryWagE.length; j++) {
			if (!markupE.containsKey(m.mandatoryWagE[j])) {
				ne.datum = "The markup " + Mix.dress_A(
						m.mandatoryWagE[j]) + ", obbligatorio per "
						+ Mix.dress_A(m.stub) + ", does not exist.";
				ne.code = 1503;
				throw ne;
			} else if (m.optionalWagE != null) {
				for (int j1 = 0; j1 < m.optionalWagE.length; j1++) {
					if (m.mandatoryWagE[j].equals(m.optionalWagE[j1])) {
						ne.datum = "The markup " + Mix.dress_A(
								m.mandatoryWagE[j])
								+ ", cannot be both optional and mandatory.";
						ne.code = 1504;
						throw ne;
					}
				}
			}
		}
	}
}
