/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *******************************************************************************/
package org.ofbiz.entity.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javolution.text.CharArray;
import javolution.text.Text;
import javolution.xml.sax.Attributes;
import javolution.xml.sax.XMLReaderImpl;

import org.ofbiz.base.location.FlexibleLocation;
import org.ofbiz.base.util.Base64;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.base.util.template.FreeMarkerWorker;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericEntityNotFoundException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.datasource.GenericHelper;
import org.ofbiz.entity.eca.EntityEcaHandler;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelField;
import org.ofbiz.entity.transaction.GenericTransactionException;
import org.ofbiz.entity.transaction.TransactionUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;

import freemarker.ext.dom.NodeModel;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateHashModel;

/**
 * SAX XML Parser Content Handler for Entity Engine XML files
 */
public class EntitySaxReader implements javolution.xml.sax.ContentHandler, ErrorHandler {

    public static final String module = EntitySaxReader.class.getName();
    public static final int DEFAULT_TX_TIMEOUT = 7200;

    protected org.xml.sax.Locator locator;
    protected Delegator delegator;
    protected EntityEcaHandler<?> ecaHandler = null;
    protected GenericValue currentValue = null;
    protected CharSequence currentFieldName = null;
    protected CharSequence currentFieldValue = null;
    protected long numberRead = 0;
    protected long numberCreated = 0;
    protected long numberUpdated = 0;
    protected long numberReplaced = 0;
    protected long numberDeleted = 0;
    protected long numberSkipped = 0;

    protected int valuesPerWrite = 100;
    protected int valuesPerMessage = 1000;
    protected int transactionTimeout = 7200;
    protected boolean useTryInsertMethod = false;
    protected boolean maintainTxStamps = false;
    protected boolean createDummyFks = false;
    protected boolean checkDataOnly = false;
    @Deprecated
    protected boolean doCacheClear = true;
    protected boolean disableEeca = false;
    protected enum Action {CREATE, CREATE_UPDATE, CREATE_REPLACE, DELETE}; 
    protected List<String> actionTags = UtilMisc.toList("create", "create-update", "create-replace", "delete");
    protected Action currentAction = Action.CREATE_UPDATE;
    protected List<Object> messageList = null;

    protected List<GenericValue> valuesToWrite = new ArrayList<GenericValue>(valuesPerWrite);
    protected List<GenericValue> valuesToDelete = new ArrayList<GenericValue>(valuesPerWrite);

    protected boolean isParseForTemplate = false;
    protected CharSequence templatePath = null;
    protected Node rootNodeForTemplate = null;
    protected Node currentNodeForTemplate = null;
    protected Document documentForTemplate = null;

    protected EntitySaxReader() {}

    public EntitySaxReader(Delegator delegator, int transactionTimeout) {
        // clone the delegator right off so there is no chance of making change to the initial object
        this.delegator = delegator.cloneDelegator();
        this.transactionTimeout = transactionTimeout;
    }

    public EntitySaxReader(Delegator delegator) {
        this(delegator, DEFAULT_TX_TIMEOUT);
    }

    public int getValuesPerWrite() {
        return this.valuesPerWrite;
    }

    public void setValuesPerWrite(int valuesPerWrite) {
        this.valuesPerWrite = valuesPerWrite;
    }

    public int getValuesPerMessage() {
        return this.valuesPerMessage;
    }

    public void setValuesPerMessage(int valuesPerMessage) {
        this.valuesPerMessage = valuesPerMessage;
    }

    public int getTransactionTimeout() {
        return this.transactionTimeout;
    }

    public void setUseTryInsertMethod(boolean value) {
        this.useTryInsertMethod = value;
    }

    public void setTransactionTimeout(int transactionTimeout) throws GenericTransactionException {
        if (this.transactionTimeout != transactionTimeout) {
            TransactionUtil.setTransactionTimeout(transactionTimeout);
            this.transactionTimeout = transactionTimeout;
        }
    }

    public boolean getMaintainTxStamps() {
        return this.maintainTxStamps;
    }

    public void setMaintainTxStamps(boolean maintainTxStamps) {
        this.maintainTxStamps = maintainTxStamps;
    }

    public boolean getCreateDummyFks() {
        return this.createDummyFks;
    }

    public void setCreateDummyFks(boolean createDummyFks) {
        this.createDummyFks = createDummyFks;
    }

    public boolean getCheckDataOnly() {
        return this.checkDataOnly;
    }

    public void setCheckDataOnly(boolean checkDataOnly) {
        this.checkDataOnly = checkDataOnly;
    }

    @Deprecated
    public boolean getDoCacheClear() {
        return this.doCacheClear;
    }

    @Deprecated
    public void setDoCacheClear(boolean doCacheClear) {
        this.doCacheClear = doCacheClear;
    }

    public boolean getDisableEeca() {
        return this.disableEeca;
    }

    public List<Object> getMessageList() {
        if (this.checkDataOnly && this.messageList == null) {
            messageList = new LinkedList<Object>();
        }
        return this.messageList;
    }

    public void setMessageList(List<Object> messageList) {
        this.messageList = messageList;
    }

    public void setDisableEeca(boolean disableEeca) {
        this.disableEeca = disableEeca;
        if (disableEeca) {
            if (this.ecaHandler == null) {
                this.ecaHandler = delegator.getEntityEcaHandler();
            }
            this.delegator.setEntityEcaHandler(null);
        } else {
            if (ecaHandler != null) {
                this.delegator.setEntityEcaHandler(ecaHandler);
            }
        }
    }

    public void setAction(Action action) {
        this.currentAction = action;
    }

    public Action getAction() {
        return this.currentAction;
    }

    public long parse(String content) throws SAXException, java.io.IOException {
        if (content == null) {
            Debug.logWarning("content was null, doing nothing", module);
            return 0;
        }
        ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes("UTF-8"));

        return this.parse(bis, "Internal Content");
    }

    public long parse(URL location) throws SAXException, java.io.IOException {
        if (location == null) {
            Debug.logWarning("location URL was null, doing nothing", module);
            return 0;
        }
        Debug.logImportant("Beginning import from URL: " + location.toExternalForm(), module);
        InputStream is = null;
        long numberRead = 0;
        try {
            is = location.openStream();
            numberRead = this.parse(is, location.toString());
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch(Exception e) {}
            }
        }
        return numberRead;
    }

    public long parse(InputStream is, String docDescription) throws SAXException, java.io.IOException {

        /* NOTE: this method is not used because it doesn't work with various parsers...
         String orgXmlSaxDriver = System.getProperty("org.xml.sax.driver");
         if (UtilValidate.isEmpty(orgXmlSaxDriver)) orgXmlSaxDriver = "org.apache.xerces.parsers.SAXParser";
         XMLReader reader = XMLReaderFactory.createXMLReader(orgXmlSaxDriver);
         */

        /* This code is for a standard SAXParser and XMLReader like xerces or such; for speed we are using the Javolution reader
        XMLReader reader = null;

        try {
            SAXParserFactory parserFactory = SAXParserFactory.newInstance();
            SAXParser parser = parserFactory.newSAXParser();

            reader = parser.getXMLReader();
        } catch (javax.xml.parsers.ParserConfigurationException e) {
            Debug.logError(e, "Failed to get a SAX XML parser", module);
            throw new IllegalStateException("Failed to get a SAX XML parser");
        }
        */

        XMLReaderImpl parser = new XMLReaderImpl();

        parser.setContentHandler(this);
        parser.setErrorHandler(this);
        // LocalResolver lr = new UtilXml.LocalResolver(new DefaultHandler());
        // reader.setEntityResolver(lr);

        numberRead = 0;
        try {
            boolean beganTransaction = false;
            if (transactionTimeout > -1) {
                beganTransaction = TransactionUtil.begin(transactionTimeout);
                Debug.logImportant("Transaction Timeout set to " + transactionTimeout / 3600 + " hours (" + transactionTimeout + " seconds)", module);
            }
            try {
                parser.parse(is);
                // make sure all of the values to write got written...
                if (! valuesToWrite.isEmpty()) {
                    writeValues(valuesToWrite);
                    valuesToWrite.clear();
                }
                if (! valuesToDelete.isEmpty()) {
                    delegator.removeAll(valuesToDelete);
                    valuesToDelete.clear();
                }
                TransactionUtil.commit(beganTransaction);
            } catch (Exception e) {
                String errMsg = "An error occurred saving the data, rolling back transaction (" + beganTransaction + ")";
                Debug.logError(e, errMsg, module);
                TransactionUtil.rollback(beganTransaction, errMsg, e);
                throw new SAXException("A transaction error occurred reading data", e);
            }
        } catch (GenericTransactionException e) {
            throw new SAXException("A transaction error occurred reading data", e);
        }
        Debug.logImportant("Finished " + numberRead + " values from " + docDescription, module);
        if (Debug.verboseOn()) { 
            Debug.logVerbose("  Detail created : " + numberCreated + ", skipped : " + numberSkipped +
                    ", updated : " + numberUpdated + ", replaced : " + numberReplaced +
                    ", deleted : " + numberDeleted, module);
        }
        return numberRead;
    }

    protected void writeValues(List<GenericValue> valuesToWrite) throws GenericEntityException {
        if (this.checkDataOnly) {
            EntityDataAssert.checkValueList(valuesToWrite, delegator, this.getMessageList());
        } else {
            delegator.storeAll(valuesToWrite, doCacheClear, createDummyFks);
        }
    }

    public void characters(char[] values, int offset, int count) throws org.xml.sax.SAXException {
        if (isParseForTemplate) {
            // if null, don't worry about it
            if (this.currentNodeForTemplate != null) {
                Node newNode = this.documentForTemplate.createTextNode(new String(values, offset, count));
                this.currentNodeForTemplate.appendChild(newNode);
            }
            return;
        }

        if (currentValue != null && currentFieldName != null) {
            Text value = Text.valueOf(values, offset, count);

            // Debug.logInfo("characters: value=" + value, module);
            if (currentFieldValue == null) {
                currentFieldValue = value;
            } else {
                currentFieldValue = Text.valueOf(currentFieldValue).concat(value);
            }
        }
    }

    public void endDocument() throws org.xml.sax.SAXException {}

    public void endElement(CharArray namespaceURI, CharArray localName, CharArray fullName) throws org.xml.sax.SAXException {
        if (Debug.verboseOn()) Debug.logVerbose("endElement: localName=" + localName + ", fullName=" + fullName + ", numberRead=" + numberRead, module);
        String fullNameString = fullName.toString();
        if ("entity-engine-xml".equals(fullNameString)) {
            return;
        }
        if ("entity-engine-transform-xml".equals(fullNameString)) {
            // transform file & parse it, then return
            URL templateUrl = null;
            try {
                templateUrl = FlexibleLocation.resolveLocation(templatePath.toString());
            } catch (MalformedURLException e) {
                throw new SAXException("Could not find transform template with resource path [" + templatePath + "]; error was: " + e.toString());
            }

            if (templateUrl == null) {
                throw new SAXException("Could not find transform template with resource path: " + templatePath);
            } else {
                try {
                    Reader templateReader = new InputStreamReader(templateUrl.openStream());

                    StringWriter outWriter = new StringWriter();
                    Configuration config = new Configuration();
                    config.setObjectWrapper(FreeMarkerWorker.getDefaultOfbizWrapper());
                    config.setSetting("datetime_format", "yyyy-MM-dd HH:mm:ss.SSS");

                    Template template = new Template("FMImportFilter", templateReader, config);
                    NodeModel nodeModel = NodeModel.wrap(this.rootNodeForTemplate);

                    Map<String, Object> context = new HashMap<String, Object>();
                    TemplateHashModel staticModels = FreeMarkerWorker.getDefaultOfbizWrapper().getStaticModels();
                    context.put("Static", staticModels);

                    context.put("doc", nodeModel);
                    template.process(context, outWriter);
                    String s = outWriter.toString();
                    if (Debug.verboseOn()) Debug.logVerbose("transformed xml: " + s, module);

                    EntitySaxReader reader = new EntitySaxReader(delegator);
                    reader.setUseTryInsertMethod(this.useTryInsertMethod);
                    try {
                        reader.setTransactionTimeout(this.transactionTimeout);
                    } catch (GenericTransactionException e1) {
                        // couldn't set tx timeout, shouldn't be a big deal
                    }

                    numberRead += reader.parse(s);
                } catch (TemplateException e) {
                    throw new SAXException("Error storing value", e);
                } catch (IOException e) {
                    throw new SAXException("Error storing value", e);
                }
            }

            return;
        }

        if (isParseForTemplate) {
            this.currentNodeForTemplate = this.currentNodeForTemplate.getParentNode();
            return;
        }

        //Test if end action tag, set action to default
        if (actionTags.contains(fullNameString)) {
            setAction(Action.CREATE_UPDATE);
            return;
        }

        if (currentValue != null) {
            if (currentFieldName != null) {
                if (UtilValidate.isNotEmpty(currentFieldValue)) {
                    if (currentValue.getModelEntity().isField(currentFieldName.toString())) {
                        ModelEntity modelEntity = currentValue.getModelEntity();
                        ModelField modelField = modelEntity.getField(currentFieldName.toString());
                        String type = modelField.getType();
                        if (type != null && type.equals("blob")) {
                            byte strData[] = new byte[currentFieldValue.length()];
                            strData = currentFieldValue.toString().getBytes();
                            byte binData[] = new byte[currentFieldValue.length()];
                            binData = Base64.base64Decode(strData);
                            currentValue.setBytes(currentFieldName.toString(), binData);
                        } else {
                            currentValue.setString(currentFieldName.toString(), currentFieldValue.toString());
                        }
                    } else {
                        Debug.logWarning("Ignoring invalid field name [" + currentFieldName + "] found for the entity: " + currentValue.getEntityName() + " with value=" + currentFieldValue, module);
                    }
                    currentFieldValue = null;
                }
                currentFieldName = null;
            } else {
                // before we write currentValue check to see if PK is there, if not and it is one field, generate it from a sequence using the entity name
                if (!currentValue.containsPrimaryKey()) {
                    if (currentValue.getModelEntity().getPksSize() == 1) {
                        ModelField modelField = currentValue.getModelEntity().getOnlyPk();
                        String newSeq = delegator.getNextSeqId(currentValue.getEntityName());
                        currentValue.setString(modelField.getName(), newSeq);
                    } else {
                        throw new SAXException("Cannot store value with incomplete primary key with more than 1 primary key field: " + currentValue);
                    }
                }

                try {
                    boolean exist = true;
                    boolean skip = false;
                    //if verbose on, check if entity exist on database for count each action
                    //It's necessay to check also for specific action CREATE and DELETE to ensure it's ok
                    if (Action.CREATE == currentAction || Action.DELETE == currentAction || Debug.verboseOn()) {
                        GenericHelper helper = delegator.getEntityHelper(currentValue.getEntityName());
                        if (currentValue.containsPrimaryKey()) {
                            try {
                                helper.findByPrimaryKey(currentValue.getPrimaryKey());
                            } catch (GenericEntityNotFoundException e) {exist = false;}
                        }
                        if (Action.CREATE == currentAction && exist) { skip = true; }
                        else if (Action.DELETE == currentAction && ! exist) { skip = true; }
                    }
                    if (! skip) {
                        if (this.useTryInsertMethod && !this.checkDataOnly) {
                            if (Action.CREATE == currentAction) { currentValue.create(); }
                            else if (Action.DELETE == currentAction) {
                                try {
                                    currentValue.remove();
                                } catch (GenericEntityException e1) {
                                    String errMsg = "Error deleting value";
                                    Debug.logError(e1, errMsg, module);
                                    throw new SAXException(errMsg, e1);
                                }
                            } else {
                                // this technique is faster for data sets where most, if not all, values do not already exist in the database
                                try {
                                    currentValue.create();
                                } catch (GenericEntityException e1) {
                                    // create failed, try a store, if that fails too we have a real error and the catch outside of this should handle it
                                    currentValue.store();
                                }
                            }
                        } else {
                            if (Action.DELETE == currentAction) {
                                valuesToDelete.add(currentValue);
                                if (valuesToDelete.size() >= valuesPerWrite) {
                                    delegator.removeAll(valuesToDelete, doCacheClear);
                                    valuesToDelete.clear();
                                }
                            } else {
                                valuesToWrite.add(currentValue);
                                if (valuesToWrite.size() >= valuesPerWrite) {
                                    writeValues(valuesToWrite);
                                    valuesToWrite.clear();
                                }
                            }
                        }
                    }
                    numberRead++;
                    if (Debug.verboseOn()) countValue(skip, exist);
                    if ((numberRead % valuesPerMessage) == 0) {
                        Debug.logImportant("Another " + valuesPerMessage + " values imported: now up to " + numberRead, module);
                    }
                    currentValue = null;
                } catch (GenericEntityException e) {
                    String errMsg = "Error storing value";
                    Debug.logError(e, errMsg, module);
                    throw new SAXException(errMsg, e);
                }
            }
        }
    }

    //Use for detail the loading entities
    protected void countValue(boolean skip, boolean exist) {
        if (skip) numberSkipped++;
        else if (Action.DELETE == currentAction) numberDeleted++;
        else if (Action.CREATE == currentAction || ! exist) numberCreated++;
        else if (Action.CREATE_REPLACE == currentAction) numberReplaced++;
        else numberUpdated++;
    }

    public void endPrefixMapping(CharArray prefix) throws org.xml.sax.SAXException {}

    public void ignorableWhitespace(char[] values, int offset, int count) throws org.xml.sax.SAXException {
        // String value = new String(values, offset, count);
        // Debug.logInfo("ignorableWhitespace: value=" + value, module);
    }

    public void processingInstruction(CharArray target, CharArray instruction) throws org.xml.sax.SAXException {}

    public void setDocumentLocator(org.xml.sax.Locator locator) {
        this.locator = locator;
    }

    public void skippedEntity(CharArray name) throws org.xml.sax.SAXException {}

    public void startDocument() throws org.xml.sax.SAXException {}

    public void startElement(CharArray namepsaceURI, CharArray localName, CharArray fullName, Attributes attributes) throws org.xml.sax.SAXException {
        if (Debug.verboseOn()) Debug.logVerbose("startElement: localName=" + localName + ", fullName=" + fullName + ", attributes=" + attributes, module);
        String fullNameString = fullName.toString();
        if ("entity-engine-xml".equals(fullNameString)) {
            // check the maintain-timestamp flag
            CharSequence maintainTx = attributes.getValue("maintain-timestamps");
            if (maintainTx != null) {
                this.setMaintainTxStamps("true".equalsIgnoreCase(maintainTx.toString()));
            }

            // check the do-cache-clear flag
            @Deprecated
            CharSequence doCacheClear = attributes.getValue("do-cache-clear");
            if (doCacheClear != null) {
                this.setDoCacheClear("true".equalsIgnoreCase(doCacheClear.toString()));
            }

            // check the disable-eeca flag
            CharSequence ecaDisable = attributes.getValue("disable-eeca");
            if (ecaDisable != null) {
                this.setDisableEeca("true".equalsIgnoreCase(ecaDisable.toString()));
            }

            // check the use-dummy-fk flag
            CharSequence dummyFk = attributes.getValue("create-dummy-fk");
            if (dummyFk != null) {
                this.setCreateDummyFks("true".equalsIgnoreCase(dummyFk.toString()));
            }

            return;
        }

        if ("entity-engine-transform-xml".equals(fullNameString)) {
            templatePath = attributes.getValue("template");
            isParseForTemplate = true;
            documentForTemplate = UtilXml.makeEmptyXmlDocument();
            return;
        }

        if (isParseForTemplate) {
            Element newElement = this.documentForTemplate.createElement(fullNameString);
            int length = attributes.getLength();
            for (int i = 0; i < length; i++) {
                CharSequence name = attributes.getLocalName(i);
                CharSequence value = attributes.getValue(i);

                if (UtilValidate.isEmpty(name)) {
                    name = attributes.getQName(i);
                }
                newElement.setAttribute(name.toString(), value.toString());
            }

            if (this.currentNodeForTemplate == null) {
                this.currentNodeForTemplate = newElement;
                this.rootNodeForTemplate = newElement;
            } else {
                this.currentNodeForTemplate.appendChild(newElement);
                this.currentNodeForTemplate = newElement;
            }
            return;
        }

        //Test if action change
        if (actionTags.contains(fullNameString)) {
            if ("create".equals(fullNameString)) setAction(Action.CREATE);
            if ("create-update".equals(fullNameString)) setAction(Action.CREATE_UPDATE);
            if ("create-replace".equals(fullNameString)) setAction(Action.CREATE_REPLACE);
            if ("delete".equals(fullNameString)) setAction(Action.DELETE);
            return;
        }

        if (currentValue != null) {
            // we have a nested value/CDATA element
            currentFieldName = fullName;
        } else {
            String entityName = fullNameString;

            // if a dash or colon is in the tag name, grab what is after it
            if (entityName.indexOf('-') > 0) {
                entityName = entityName.substring(entityName.indexOf('-') + 1);
            }
            if (entityName.indexOf(':') > 0) {
                entityName = entityName.substring(entityName.indexOf(':') + 1);
            }

            try {
                currentValue = delegator.makeValue(entityName);
                // TODO: do we really want this? it makes it so none of the values imported have create/update timestamps set
                // DEJ 10/16/04 I think they should all be stamped, so commenting this out
                // JAZ 12/10/04 I think it should be specified when creating the reader
                if (this.maintainTxStamps) {
                    currentValue.setIsFromEntitySync(true);
                }
            } catch (Exception e) {
                Debug.logError(e, module);
            }

            if (currentValue != null) {
                int length = attributes.getLength();
                List<String> absentFields = null;
                if (Action.CREATE_REPLACE == currentAction) {
                    //get all non pk fields
                    ModelEntity currentEntity = currentValue.getModelEntity();
                    absentFields = currentEntity.getNoPkFieldNames();
                    absentFields.removeAll(currentEntity.getAutomaticFieldNames());
                }

                for (int i = 0; i < length; i++) {
                    CharSequence name = attributes.getLocalName(i);
                    CharSequence value = attributes.getValue(i);

                    if (UtilValidate.isEmpty(name)) {
                        name = attributes.getQName(i);
                    }
                    try {
                        // treat empty strings as nulls, but do NOT ignore them, instead set as null and update
                        if (value != null) {
                            if (currentValue.getModelEntity().isField(name.toString())) {
                                String valueString = (value.length() > 0 ? value.toString() : null);
                                currentValue.setString(name.toString(), valueString);
                                if (Action.CREATE_REPLACE == currentAction && absentFields != null) absentFields.remove(name);
                            } else {
                                Debug.logWarning("Ignoring invalid field name [" + name + "] found for the entity: " + currentValue.getEntityName() + " with value=" + value, module);
                            }
                        }
                    } catch (Exception e) {
                        Debug.logWarning(e, "Could not set field " + entityName + "." + name + " to the value " + value, module);
                    }
                }
                if (Action.CREATE_REPLACE == currentAction && absentFields != null) {
                    for (String fieldName : absentFields) {
                        currentValue.set(fieldName, null);
                    }
                }
            }
        }
    }

    //public void startPrefixMapping(String prefix, String uri) throws org.xml.sax.SAXException {}
    public void startPrefixMapping(CharArray arg0, CharArray arg1) throws SAXException {}

    // ======== ErrorHandler interface implementations ========

    public void error(org.xml.sax.SAXParseException exception) throws org.xml.sax.SAXException {
        Debug.logWarning(exception, "Error reading XML on line " + exception.getLineNumber() + ", column " + exception.getColumnNumber(), module);
    }

    public void fatalError(org.xml.sax.SAXParseException exception) throws org.xml.sax.SAXException {
        Debug.logError(exception, "Fatal Error reading XML on line " + exception.getLineNumber() + ", column " + exception.getColumnNumber(), module);
        throw new SAXException("Fatal Error reading XML on line " + exception.getLineNumber() + ", column " + exception.getColumnNumber(), exception);
    }

    public void warning(org.xml.sax.SAXParseException exception) throws org.xml.sax.SAXException {
        Debug.logWarning(exception, "Warning reading XML on line " + exception.getLineNumber() + ", column " + exception.getColumnNumber(), module);
    }
}
