All Downloads are FREE. Search and download functionalities are using the official Maven repository.

schema.xsd2pgschema.5.2.5.source-code.xpathparser Maven / Gradle / Ivy

/*
    xsd2pgschema - Database replication tool based on XML Schema
    Copyright 2017-2022 Masashi Yokochi

    https://sourceforge.net/projects/xsd2pgschema/

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */

import net.sf.xsd2pgschema.*;
import net.sf.xsd2pgschema.option.*;
import net.sf.xsd2pgschema.serverutil.*;
import net.sf.xsd2pgschema.type.*;
import net.sf.xsd2pgschema.xpathparser.XPathCompList;

import java.io.IOException;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.nustaq.serialization.FSTConfiguration;
import org.xml.sax.SAXException;

import com.github.antlr.grammars_v4.xpath.xpathBaseListener;
import com.github.antlr.grammars_v4.xpath.xpathLexer;
import com.github.antlr.grammars_v4.xpath.xpathListenerException;
import com.github.antlr.grammars_v4.xpath.xpathParser;
import com.github.antlr.grammars_v4.xpath.xpathParser.MainContext;

/**
 * XPath 1.0 parser with XML Schema validation.
 *
 * @author yokochi
 */
public class xpathparser {

	/**
	 * The main method.
	 *
	 * @param args the arguments
	 */
	public static void main(String[] args) {

		/** The PostgreSQL data model option. */
		PgSchemaOption option = new PgSchemaOption(true);

		option.verbose = true; // turn on verbose mode
		option.stdout_msg = false;

		/** The FST configuration. */
		FSTConfiguration fst_conf = FSTConfiguration.createDefaultConfiguration();

		fst_conf.registerClass(PgSchemaServerQuery.class,PgSchemaServerReply.class,PgSchema.class); // FST optimization

		/** The XPath query. */
		String xpath_query = "";

		/** The XPath variable reference. */
		HashMap variables = new HashMap();

		for (int i = 0; i < args.length; i++) {

			if (args[i].equals("--xsd") && i + 1 < args.length)
				option.root_schema_location = args[++i];

			else if (args[i].equals("--xpath-query") && i + 1 < args.length)
				xpath_query = args[++i];

			else if (args[i].equals("--xpath-var") && i + 1 < args.length) {
				String[] variable = args[++i].split("=");
				if (variable.length != 2) {
					System.err.println("Invalid variable definition.");
					showUsage();
				}
				variables.put(variable[0], variable[1]);
			}

			else if (args[i].equals("--doc-key"))
				option.setDocKeyOption(true);

			else if (args[i].equals("--no-doc-key"))
				option.setDocKeyOption(false);

			else if (args[i].equals("--no-rel"))
				option.cancelRelDataExt();

			else if (args[i].equals("--inline-simple-cont"))
				option.inline_simple_cont = true;

			else if (args[i].equals("--no-wild-card"))
				option.wild_card = false;

			else if (args[i].equals("--ser-key"))
				option.serial_key = true;

			else if (args[i].equals("--xpath-key"))
				option.xpath_key = true;

			else if (args[i].equals("--case-insensitive"))
				option.setCaseInsensitive();

			else if (args[i].equals("--pg-public-schema"))
				option.pg_named_schema = false;

			else if (args[i].equals("--pg-named-schema"))
				option.pg_named_schema = true;

			else if (args[i].equals("--pg-map-big-integer"))
				option.pg_integer = PgIntegerType.big_integer;

			else if (args[i].equals("--pg-map-long-integer"))
				option.pg_integer = PgIntegerType.signed_long_64;

			else if (args[i].equals("--pg-map-integer"))
				option.pg_integer = PgIntegerType.signed_int_32;

			else if (args[i].equals("--pg-map-big-decimal"))
				option.pg_decimal = PgDecimalType.big_decimal;

			else if (args[i].equals("--pg-map-double-decimal"))
				option.pg_decimal = PgDecimalType.double_precision_64;

			else if (args[i].equals("--pg-map-float-decimal"))
				option.pg_decimal = PgDecimalType.single_precision_32;

			else if (args[i].equals("--pg-map-timestamp"))
				option.pg_date = PgDateType.timestamp;

			else if (args[i].equals("--pg-map-date"))
				option.pg_date = PgDateType.date;

			else if (args[i].equals("--no-cache-xsd"))
				option.cache_xsd = false;

			else if (args[i].equals("--hash-by") && i + 1 < args.length)
				option.hash_algorithm = args[++i];

			else if (args[i].equals("--hash-size") && i + 1 < args.length)
				option.hash_size = PgHashSize.getSize(args[++i]);

			else if (args[i].equals("--ser-size") && i + 1 < args.length)
				option.ser_size = PgSerSize.getSize(args[++i]);

			else if (args[i].equals("--doc-key-name") && i + 1 < args.length)
				option.setDocumentKeyName(args[++i]);

			else if (args[i].equals("--ser-key-name") && i + 1 < args.length)
				option.setSerialKeyName(args[++i]);

			else if (args[i].equals("--xpath-key-name") && i + 1 < args.length)
				option.setXPathKeyName(args[++i]);

			else if (args[i].equals("--pg-named-schema-translation") && i + 1 < args.length)
				option.addPgNamedSchemaTranslation(args[++i]);

			else if (args[i].equals("--discarded-doc-key-name") && i + 1 < args.length)
				option.addDiscardedDocKeyName(args[++i]);

			else if (args[i].equals("--inplace-doc-key-name") && i + 1 < args.length) {
				option.addInPlaceDocKeyName(args[++i]);
				option.setDocKeyOption(false);
			}

			else if (args[i].equals("--doc-key-if-no-inplace")) {
				option.document_key_if_no_in_place = true;
				option.setDocKeyOption(false);
			}

			else if (args[i].equals("--show-orphan-table"))
				option.show_orphan_table = true;

			else if (args[i].equals("--wild-card-to-latter"))
				option.wild_card_to_latter = true;

			else if (args[i].equals("--no-pgschema-serv"))
				option.pg_schema_server = false;

			else if (args[i].equals("--pgschema-serv-host") && i + 1 < args.length)
				option.pg_schema_server_host = args[++i];

			else if (args[i].equals("--pgschema-serv-port") && i + 1 < args.length)
				option.pg_schema_server_port = Integer.valueOf(args[++i]);

			else {
				System.err.println("Illegal option: " + args[i] + ".");
				showUsage();
			}

		}

		option.resolveDocKeyOption();

		if (option.root_schema_location.isEmpty()) {
			System.err.println("XSD schema location is empty.");
			showUsage();
		}

		PgSchemaClientType client_type = PgSchemaClientType.xpath_evaluation;

		InputStream is = null;

		boolean server_alive = option.pingPgSchemaServer(fst_conf);
		boolean no_data_model = server_alive ? !option.matchPgSchemaServer(fst_conf, client_type) : true;

		if (no_data_model) {

			is = PgSchemaUtil.getSchemaInputStream(option.root_schema_location, null, false);

			if (is == null)
				showUsage();

		}

		try {

			String original_caller = MethodHandles.lookup().lookupClass().getName();

			PgSchemaClientImpl client = new PgSchemaClientImpl(is, option, fst_conf, client_type, original_caller);

			xpathLexer lexer = new xpathLexer(CharStreams.fromString(xpath_query));

			CommonTokenStream tokens = new CommonTokenStream(lexer);

			xpathParser parser = new xpathParser(tokens);
			parser.addParseListener(new xpathBaseListener());

			// validate XPath expression with schema

			MainContext main = parser.main();

			ParseTree tree = main.children.get(0);
			String main_text = main.getText();

			if (parser.getNumberOfSyntaxErrors() > 0 || tree.getSourceInterval().length() == 0)
				throw new xpathListenerException("Invalid XPath expression. (" + main_text + ")");

			XPathCompList xpath_comp_list = new XPathCompList(client.schema, tree, variables);

			if (xpath_comp_list.comps.size() == 0)
				throw new xpathListenerException("Insufficient XPath expression. (" + main_text + ")");

			xpath_comp_list.validate(false);

			if (xpath_comp_list.path_exprs.size() == 0)
				throw new xpathListenerException("Insufficient XPath expression. " + (xpath_comp_list.func_expr ? "Hint: id() function can be replaced by explicit location path expression that refers to the XML Schema(ta). " : "") + "(" + main_text + ")");

			StringBuilder sb = new StringBuilder();

			sb.append("Input XPath query:\n " + main_text + "\n");
			if (variables.size() > 0) {
				sb.append("\nInput XPath variable:\n");
				variables.entrySet().forEach(arg -> sb.append("$" + arg.getKey() + " = " + arg.getValue() + ", "));
				sb.setLength(sb.length() - 2);
				sb.append("\n");
			}
			sb.append("\nTarget path in XML Schema: " + option.root_schema_location + "\n");

			xpath_comp_list.showPathExprs(sb);

			sb.append("\nThe XPath query is valid.\n");

			System.out.print(sb.toString());

			sb.setLength(0);

			if (xpath_comp_list.updated)
				option.updatePgSchemaServer(fst_conf, client.schema, client_type, original_caller);

		} catch (IOException | ParserConfigurationException | SAXException | PgSchemaException | xpathListenerException e) {
			e.printStackTrace();
			System.exit(1);
		}

	}

	/**
	 * Show usage.
	 */
	private static void showUsage() {

		PgSchemaOption option = new PgSchemaOption(true);

		String[] usage = {
				"xpathparser: XPath 1.0 parser being aware of XML Schema",
				"Usage:  --xsd SCHEMA_LOCATION",
				"        --xpath-query XPATH_QUERY",
				"        --xpath-var KEY=VALUE (repeat until you specify all variables)",
				"        --no-rel (turn off relational model extension)",
				"        --inline-simple-cont (enable inlining simple content)",
				"        --no-wild-card (turn off wild card extension)",
				"        --doc-key (append " + option.document_key_name + " column in all relations, default with relational model extension)",
				"        --no-doc-key (remove " + option.document_key_name + " column from all relations, effective only with relational model extension)",
				"        --ser-key (append " + option.serial_key_name + " column in child relation of list holder)",
				"        --xpath-key (append " + option.xpath_key_name + " column in all relations)",
				"Option: --case-insensitive (all table and column names are lowercase)",
				"        --pg-public-schema (utilize \"public\" schema, default)",
				"        --pg-named-schema (enable explicit named schema)",
				"        --pg-map-big-integer (map xs:integer to BigInteger according to the W3C rules)",
				"        --pg-map-long-integer (map xs:integer to signed long 64 bits)",
				"        --pg-map-integer (map xs:integer to signed int 32 bits, default)",
				"        --pg-map-big-decimal (map xs:decimal to BigDecimal according to the W3C rules, default)",
				"        --pg-map-double-decimal (map xs:decimal to double precision 64 bits)",
				"        --pg-map-float-decimal (map xs:decimal to single precision 32 bits)",
				"        --pg-map-timestamp (map xs:date to PostgreSQL timestamp type according to the W3C rules)",
				"        --pg-map-date (map xs:date to PostgreSQL date type, default)",
				"        --no-cache-xsd (retrieve XML Schemata without caching)",
				"        --hash-by ALGORITHM [MD2 | MD5 | SHA-1 (default) | SHA-224 | SHA-256 | SHA-384 | SHA-512]",
				"        --hash-size BIT_SIZE [int (32 bits) | long (64 bits, default) | native (default bits of algorithm) | debug (string)]",
				"        --ser-size BIT_SIZE [short (16 bits) | int (32 bits, default)]",
				"        --doc-key-name DOC_KEY_NAME (default=\"" + option.def_document_key_name + "\")",
				"        --ser-key-name SER_KEY_NAME (default=\"" + option.def_serial_key_name + "\")",
				"        --xpath-key-name XPATH_KEY_NAME (default=\"" + option.def_xpath_key_name + "\")",
				"        --pg-named-schema-translation DEFAULT_PREFIX:PG_NAMED_SCHEMA",
				"        --discarded-doc-key-name DISCARDED_DOCUMENT_KEY_NAME",
				"        --inplace-doc-key-name INPLACE_DOCUMENT_KEY_NAME",
				"        --doc-key-if-no-inplace (append document key if no in-place document key, select --no-doc-key options by default)",
				"        --show-orphan-table (required if you mapped orphan tables during DDL generation)",
				"        --wild-card-to-latter (move wild cards to latter column)",
				"        --no-pgschema-serv (not utilize PgSchema server)",
				"        --pgschema-serv-host PG_SCHEMA_SERV_HOST_NAME (default=\"" + PgSchemaUtil.pg_schema_server_host + "\")",
				"        --pgschema-serv-port PG_SCHEMA_SERV_PORT_NUMBER (default=" + PgSchemaUtil.pg_schema_server_port + ")"
		};

		for (String s : usage)
			System.err.println(s);

		System.exit(1);

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy