/*
 * Copyright (c) 2014 Villu Ruusmann
 */
package org.jpmml.model;

import org.jpmml.schema.Version;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.XMLFilterImpl;

abstract
public class PMMLFilter extends XMLFilterImpl {

	private Version source = null;

	private Version target = null;


	public PMMLFilter(Version target){
		setTarget(target);
	}

	public PMMLFilter(XMLReader reader, Version target){
		super(reader);

		setTarget(target);
	}

	abstract
	public String filterLocalName(String localName);

	abstract
	public Attributes filterAttributes(String localName, Attributes attributes);

	@Override
	public void startPrefixMapping(String prefix, String namespaceURI) throws SAXException {

		if(("").equals(prefix)){
			updateSource(namespaceURI);

			super.startPrefixMapping("", getNamespaceURI());

			return;
		}

		super.startPrefixMapping(prefix, namespaceURI);
	}

	@Override
	public void endPrefixMapping(String prefix) throws SAXException {
		super.endPrefixMapping(prefix);
	}

	@Override
	public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attributes) throws SAXException {

		if(isFilterable(namespaceURI)){
			updateSource(namespaceURI);

			String filteredNamespaceURI = getNamespaceURI();
			String filteredLocalName = filterLocalName(localName);

			String filteredQualifiedName = formatQualifiedName(qualifiedName, filteredNamespaceURI, filteredLocalName);

			Attributes filteredAttributes = filterAttributes(localName, attributes);

			super.startElement(filteredNamespaceURI, filteredLocalName, filteredQualifiedName, filteredAttributes);

			return;
		}

		super.startElement(namespaceURI, localName, qualifiedName, attributes);
	}

	@Override
	public void endElement(String namespaceURI, String localName, String qualifiedName) throws SAXException {

		if(isFilterable(namespaceURI)){
			String filteredNamespaceURI = getNamespaceURI();
			String filteredLocalName = filterLocalName(localName);

			String filteredQualifiedName = formatQualifiedName(qualifiedName, filteredNamespaceURI, filteredLocalName);

			super.endElement(filteredNamespaceURI, filteredLocalName, filteredQualifiedName);

			return;
		}

		super.endElement(namespaceURI, localName, qualifiedName);
	}

	private boolean isFilterable(String namespaceURI){

		if(("").equals(namespaceURI)){
			return true;
		}

		return namespaceURI.startsWith("http://www.dmg.org/PMML-");
	}

	private String getNamespaceURI(){
		Version target = getTarget();

		return target.getNamespaceURI();
	}

	private void updateSource(String namespaceURI){

		if(("").equals(namespaceURI)){
			return;
		}

		Version version = Version.forNamespaceURI(namespaceURI);

		Version source = getSource();
		if(source != null && !(source).equals(version)){
			throw new IllegalStateException();
		}

		setSource(version);
	}

	public Version getSource(){
		return this.source;
	}

	private void setSource(Version source){
		this.source = source;
	}

	public Version getTarget(){
		return this.target;
	}

	private void setTarget(Version target){
		this.target = target;
	}

	static
	protected int compare(Version left, Version right){

		if(left == null || right == null){
			throw new IllegalStateException();
		}

		return (left).compareTo(right);
	}

	static
	private String formatQualifiedName(String template, String namespaceURI, String localName){

		if(("").equals(template)){
			return "";
		} // End if

		if(template.indexOf(':') > -1){
			return (namespaceURI + ":" + localName);
		}

		return localName;
	}

	static
	protected boolean hasAttribute(Attributes attributes, String localName){
		int index = attributes.getIndex("", localName);

		return (index > -1);
	}

	static
	protected Attributes setAttribute(Attributes attributes, String localName, String value){
		int index = attributes.getIndex("", localName);

		AttributesImpl result = new AttributesImpl(attributes);

		if(index < 0){
			result.addAttribute("", localName, "", "CDATA", value); // XXX
		} else

		{
			result.setValue(index, value);
		}

		return result;
	}

	static
	protected Attributes renameAttribute(Attributes attributes, String oldLocalName, String localName){
		int index = attributes.getIndex("", oldLocalName);
		if(index < 0){
			return attributes;
		}

		AttributesImpl result = new AttributesImpl(attributes);
		result.setLocalName(index, localName);
		result.setQName(index, localName); // XXX

		return result;
	}
}
@@ -1323,60 +1323,8 @@
 );%0A%0A
-%09%09%09String filteredNamespaceURI = getNamespaceURI();%0A
 %09%09%09S
@@ -1369,33 +1369,32 @@
 ame(localName);%0A
-%0A
 %09%09%09String filter
@@ -1415,64 +1415,42 @@
 e = 
-formatQualifiedName(qualifiedName, filteredNamespaceURI,
+((%22%22).equals(qualifiedName) ? %22%22 :
  fil
@@ -1562,32 +1562,27 @@
 tartElement(
-filtered
+get
 NamespaceURI
@@ -1573,32 +1573,34 @@
 (getNamespaceURI
+()
 , filteredLocalN
@@ -1900,60 +1900,8 @@
 ))%7B%0A
-%09%09%09String filteredNamespaceURI = getNamespaceURI();%0A
 %09%09%09S
@@ -1954,17 +1954,16 @@
 lName);%0A
-%0A
 %09%09%09Strin
@@ -1992,64 +1992,42 @@
 e = 
-formatQualifiedName(qualifiedName, filteredNamespaceURI,
+((%22%22).equals(qualifiedName) ? %22%22 :
  fil
@@ -2064,24 +2064,19 @@
 Element(
-filtered
+get
 Namespac
@@ -2079,16 +2079,18 @@
 spaceURI
+()
 , filter
@@ -3230,275 +3230,8 @@
 %09%7D%0A%0A
-%09static%0A%09private String formatQualifiedName(String template, String namespaceURI, String localName)%7B%0A%0A%09%09if((%22%22).equals(template))%7B%0A%09%09%09return %22%22;%0A%09%09%7D // End if%0A%0A%09%09if(template.indexOf(':') %3E -1)%7B%0A%09%09%09return (namespaceURI + %22:%22 + localName);%0A%09%09%7D%0A%0A%09%09return localName;%0A%09%7D%0A%0A
 %09sta

Assume 'unqualified' element form