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

org.milyn.javabean.dynamic.visitor.UnknownElementDataReaper Maven / Gradle / Ivy

The newest version!
/*
 * Milyn - Copyright (C) 2006 - 2010
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License (version 2.1) as published by the Free Software
 *  Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  See the GNU Lesser General Public License for more details:
 *  http://www.gnu.org/licenses/lgpl.txt
 */

package org.milyn.javabean.dynamic.visitor;

import org.milyn.SmooksException;
import org.milyn.delivery.Fragment;
import org.milyn.delivery.dom.serialize.DefaultSerializationUnit;
import org.milyn.io.StreamUtils;
import org.milyn.javabean.dynamic.BeanMetadata;
import org.milyn.javabean.lifecycle.BeanContextLifecycleEvent;
import org.w3c.dom.*;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Unknown element data reaper.
 *
 * Models can sometimes be created from XML which contains valid elements that are not being mapped into the model.
 * We don't want to loose this data in the model, so we capture it as "pre
 * 
 * @author [email protected]
 */
public class UnknownElementDataReaper {

    public static String getPreText(Element element, List beanMetadataSet, BeanContextLifecycleEvent event) {
        StringWriter serializeWriter = new StringWriter();
        List toSerializeNodes = new ArrayList();
        Node current = element;

        // Skip back through the siblings until we get an element that has an associated
        // bean...
        while(current != null) {
            current = current.getPreviousSibling();

            if(current == null) {
                // This will result in all siblings back to the start
                // of this sibling set...
                break;
            }

            if(current instanceof Element) {
                if(isOnModelSourcePath(new Fragment((Element) current), beanMetadataSet)) {
                    // The "previous" element is associated with the creation/population of a bean in the
                    // model, so stop here...
                    break;
                }
            }

            toSerializeNodes.add(0, current);
        }

        for(Node node : toSerializeNodes) {
            try {
                serialize(node, serializeWriter);
            } catch (IOException e) {
                throw new SmooksException("Unexpected pre-text node serialization exception.", e);
            }
        }

        // Get rid of leading and space characters (only spaces - not all whitespace).
        // This helps eliminate ugly indentation issues in the serialized XML...
        String xml;
        try {
            xml = normalizeLines(serializeWriter.toString());
        } catch (IOException e) {
            throw new SmooksException("Unexpected pre-text node serialization exception while attempting to remove excess whitespace.", e);
        }
        StringBuilder trimEnd = new StringBuilder(xml);
        while(trimEnd.length() > 0 && trimEnd.charAt(0) == ' ') {
            trimEnd.deleteCharAt(0);
        }
        while(trimEnd.length() > 1 && trimEnd.charAt(0) == '\n' && trimEnd.charAt(1) == '\n') {
            trimEnd.deleteCharAt(0);
        }
        while(trimEnd.length() > 0 && trimEnd.charAt(trimEnd.length() - 1) == ' ') {
            trimEnd.deleteCharAt(trimEnd.length() - 1);
        }
        while(trimEnd.length() > 1 && trimEnd.charAt(trimEnd.length() - 1) == '\n' && trimEnd.charAt(trimEnd.length() - 2) == '\n') {
            trimEnd.deleteCharAt(trimEnd.length() - 1);
        }

        return trimEnd.toString();
    }

    private static boolean isOnModelSourcePath(Fragment fragment, List beanMetadataSet) {
        for(BeanMetadata beanMetadata : beanMetadataSet) {
            if(fragment.equals(beanMetadata.getCreateSource())) {
                return true;
            }

            for(Fragment populateSource : beanMetadata.getPopulateSources()) {
                if(fragment.isParentFragment(populateSource)) {
                    return true;
                }
            }
        }

        return false;
    }

    public static String normalizeLines(String xml) throws IOException {
        StringBuffer stringBuf = new StringBuffer();
        int xmlLength = xml.length();

        for(int i = 0; i < xmlLength; i++) {
            char character = xml.charAt(i);
            if(character != '\r') {
                stringBuf.append(character);
            }
        }

        return stringBuf.toString();
    }

    private static DefaultSerializationUnit serializationUnit;
    static {
        serializationUnit = new DefaultSerializationUnit();
        serializationUnit.setCloseEmptyElements(true);
        serializationUnit.setRewriteEntities(true); 
    }
    private static void serialize(Node node, Writer writer) throws IOException {
        switch(node.getNodeType()) {
            case Node.ELEMENT_NODE: {
                Element element = (Element) node;
                NodeList children = element.getChildNodes();
                int childCount = children.getLength();

                serializationUnit.writeElementStart(element, writer);

                // Write the child nodes...
                for(int i = 0; i < childCount; i++) {
                    serialize(children.item(i), writer);
                }

                serializationUnit.writeElementEnd(element, writer);
                break;
            }
            case Node.TEXT_NODE: {
                serializationUnit.writeElementText((Text)node, writer, null);
                break;
            }
            case Node.COMMENT_NODE: {
                serializationUnit.writeElementComment((Comment)node, writer, null);
                break;
            }
            case Node.CDATA_SECTION_NODE: {
                serializationUnit.writeElementCDATA((CDATASection)node, writer, null);
                break;
            }
            case Node.ENTITY_REFERENCE_NODE: {
                serializationUnit.writeElementEntityRef((EntityReference)node, writer, null);
                break;
            }
            default: {
                break;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy