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

org.eclipse.persistence.internal.oxm.record.MarshalRecord Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Blaise Doughan - 2.5 - initial implementation
package org.eclipse.persistence.internal.oxm.record;

import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.internal.core.helper.CoreField;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.oxm.ConversionManager;
import org.eclipse.persistence.internal.oxm.Marshaller;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.XPathNode;
import org.w3c.dom.Node;

import javax.xml.namespace.QName;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;

/**
 * This class represents marshal record behaviour that is specific to the SAX
 * platform.
 */
public interface MarshalRecord<
    ABSTRACT_SESSION extends CoreAbstractSession,
    FIELD extends CoreField,
    MARSHALLER extends Marshaller,
    NAMESPACE_RESOLVER extends NamespaceResolver> extends AbstractMarshalRecord {

    void add(FIELD field, Object value);

    void addGroupingElement(XPathNode holderXPathNode);

    void afterContainmentMarshal(Object object, Object value);

    @Override void attribute(String namespaceURI, String localPart,
            String qualifiedName, String value);

    void attribute(XPathFragment nextFragment,
            NAMESPACE_RESOLVER namespaceResolver, Object fieldValue,
            QName schemaType);

    void attribute(XPathFragment xPathFragment,
            NAMESPACE_RESOLVER namespaceResolver, String value);

    @Override void attributeWithoutQName(String namespaceURI,
            String localName, String prefix, String value);

    void beforeContainmentMarshal(Object value);

    void cdata(String string);

    void characters(QName schemaType, Object objectValue,
            String mimeType, boolean b);

    void characters(String c_id);

    void closeStartElement();

    void closeStartGroupingElements(XPathFragment groupingFragment);

    void emptyAttribute(XPathFragment xPathFragment,
            NAMESPACE_RESOLVER namespaceResolver);

    boolean emptyCollection(XPathFragment xPathFragment,
            NAMESPACE_RESOLVER namespaceResolver, boolean b);

    void emptyComplex(XPathFragment xPathFragment,
            NAMESPACE_RESOLVER namespaceResolver);

    void emptySimple(NAMESPACE_RESOLVER namespaceResolver);

    void endCollection();

    void endElement(XPathFragment xPathFragment,
            NAMESPACE_RESOLVER namespaceResolver);

    void endPrefixMapping(String prefix);

    void flush();

    void forceValueWrapper();

    CoreAttributeGroup getCurrentAttributeGroup();

    CycleDetectionStack  getCycleDetectionStack();

    ArrayList getGroupingElements();

    XPathFragment getTextWrapperFragment();

    String getValueToWrite(QName schemaType, Object fieldValue,
            ConversionManager conversionManager);

    @Override boolean hasCustomNamespaceMapper();

    boolean isWrapperAsCollectionName();

    @Override boolean isXOPPackage();

    @Override void namespaceDeclaration(String generatedPrefix, String namespaceURI);

    void nilComplex(XPathFragment xPathFragment,
            NAMESPACE_RESOLVER namespaceResolver);

    void nilSimple(NAMESPACE_RESOLVER namespaceResolver);

    void node(Node item, NAMESPACE_RESOLVER namespaceResolver);

    void openStartElement(XPathFragment xPathFragment,
            NAMESPACE_RESOLVER namespaceResolver);

    XPathFragment openStartGroupingElements(
            NAMESPACE_RESOLVER namespaceResolver);

    void popAttributeGroup();

    void predicateAttribute(XPathFragment anXPathFragment,
            NAMESPACE_RESOLVER namespaceResolver);

    void pushAttributeGroup(CoreAttributeGroup group);

    @Override void removeExtraNamespacesFromNamespaceResolver(List extraNamespaces, CoreAbstractSession session);

    void removeGroupingElement(XPathNode holderXPathNode);

    void setGroupingElement(ArrayList object);

    @Override void setLeafElementType(QName leafElementType);

    @Override void setMarshaller(MARSHALLER marshaller);

    void startCollection();

    void startPrefixMapping(String prefix, String uri);

    /**
     * A Stack-like List, used to detect object cycles during marshal operations.
     */
    class CycleDetectionStack extends AbstractList {

        private Object[] data = new Object[8];

        int currentIndex = 0;

        public void push(E item) {
            if (currentIndex == data.length) {
                growArray();
            }
            data[currentIndex] = item;
            currentIndex++;
        }

        private void growArray() {
            Object[] newArray = new Object[data.length * 2];
            System.arraycopy(data, 0, newArray, 0, data.length);
            data = newArray;
        }

        public Object pop() {
            Object o = data[currentIndex - 1];
            data[currentIndex - 1] = null;
            currentIndex--;
            return o;
        }

        public boolean contains(Object item, boolean equalsUsingIdentity) {
            if (equalsUsingIdentity) {
                for (int i = 0; i < currentIndex; i++) {
                    if (data[i] == item) {
                        return true;
                    }
                }
            } else {
                for (int i = 0; i < currentIndex; i++) {
                    if (data[i] != null && data[i].equals(item)) {
                        return true;
                    }
                }
            }
            return false;
        }

        public String getCycleString() {
            StringBuilder sb = new StringBuilder();
            int i = size() - 1;
            Object obj = get(i);
            sb.append(obj);
            Object x;
            do {
                sb.append(" -> ");
                x = get(--i);
                sb.append(x);
            } while (obj != x);

            return sb.toString();
        }

        @Override
        public Object get(int index) {
            return data[index];
        }

        @Override
        public int size() {
            return currentIndex;
        }

    }

}