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

org.nakedobjects.plugins.remoting.shared.ObjectEncoderSerializer Maven / Gradle / Ivy

package org.nakedobjects.plugins.remoting.shared;

import java.util.Enumeration;

import org.nakedobjects.metamodel.adapter.NakedObject;
import org.nakedobjects.metamodel.adapter.ResolveState;
import org.nakedobjects.metamodel.adapter.oid.Oid;
import org.nakedobjects.metamodel.commons.ensure.Assert;
import org.nakedobjects.metamodel.commons.exceptions.NakedObjectException;
import org.nakedobjects.metamodel.commons.exceptions.UnknownTypeException;
import org.nakedobjects.metamodel.facets.actcoll.typeof.TypeOfFacet;
import org.nakedobjects.metamodel.facets.collections.modify.CollectionFacet;
import org.nakedobjects.metamodel.facets.object.encodeable.EncodeableFacet;
import org.nakedobjects.metamodel.spec.feature.NakedObjectAssociation;
import org.nakedobjects.metamodel.util.CollectionFacetUtils;
import org.nakedobjects.plugins.remoting.shared.data.CollectionData;
import org.nakedobjects.plugins.remoting.shared.data.Data;
import org.nakedobjects.plugins.remoting.shared.data.DataFactory;
import org.nakedobjects.plugins.remoting.shared.data.EncodeableObjectData;
import org.nakedobjects.plugins.remoting.shared.data.KnownObjects;
import org.nakedobjects.plugins.remoting.shared.data.ObjectData;
import org.nakedobjects.plugins.remoting.shared.data.ReferenceData;
import org.nakedobjects.runtime.persistence.PersistorUtil;

/**
 * Utility class to create Data objects representing a graph of NakedObjects.
 * 
 * As each object is serialised its resolved state is changed to SERIALIZING; any object that is marked as
 * SERIALIZING is skipped.
 */
final class ObjectEncoderSerializer {
    private ObjectEncoderDataStructure dataStructure;

    public CollectionData serializeCollection(
            final DataFactory factory,
            final NakedObject collectionAdapter,
            final int graphDepth,
            final KnownObjects knownObjects) {
        final Oid oid = collectionAdapter.getOid();
        final String collectionType = collectionAdapter.getSpecification().getFullName();
        final TypeOfFacet typeOfFacet = collectionAdapter.getSpecification().getFacet(TypeOfFacet.class);
        if (typeOfFacet == null) {
            throw new NakedObjectException("No type of facet for collection " + collectionAdapter);
        }
        final String elementType = typeOfFacet.value().getName();
        final boolean hasAllElements = collectionAdapter.isTransient() || 
                                       collectionAdapter.getResolveState().isResolved();
        ReferenceData[] elements;

        if (hasAllElements) {
            final CollectionFacet collectionFacet = CollectionFacetUtils.getCollectionFacetFromSpec(collectionAdapter);
            final Enumeration e = collectionFacet.elements(collectionAdapter);
            elements = new ReferenceData[collectionFacet.size(collectionAdapter)];
            int i = 0;
            while (e.hasMoreElements()) {
                final NakedObject element = (NakedObject) e.nextElement();
                elements[i++] = serializeObject(factory, element, graphDepth, knownObjects);
            }
        } else {
            elements = new ObjectData[0];
        }

        return factory.createCollectionData(collectionType, elementType, oid, elements, hasAllElements, collectionAdapter.getVersion());
    }

    // TODO rename to serialise.,.,.
    public final EncodeableObjectData serializeEncodeable(final DataFactory factory, final NakedObject object) {
        final EncodeableFacet facet = object.getSpecification().getFacet(EncodeableFacet.class);
        return factory.createValueData(object.getSpecification().getFullName(), facet.toEncodedString(object));
    }

    public final ReferenceData serializeObject(
            final DataFactory factory,
            final NakedObject object,
            final int depth,
            final KnownObjects knownObjects) {
        Assert.assertNotNull(object);
        return (ReferenceData) serializeObject2(factory, object, depth, knownObjects);
    }

    private final Data serializeObject2(
            final DataFactory factory,
            final NakedObject adapter,
            final int graphDepth,
            final KnownObjects knownObjects) {
        Assert.assertNotNull(adapter);

        final ResolveState resolveState = adapter.getResolveState();
        boolean isTransient = adapter.isTransient();

        if (!isTransient && (resolveState.isSerializing() || resolveState.isGhost() || graphDepth <= 0)) {
            Assert.assertNotNull("OID needed for reference", adapter, adapter.getOid());
            return factory.createIdentityData(adapter.getSpecification().getFullName(), adapter.getOid(), adapter.getVersion());
        }
        if (isTransient && knownObjects.containsKey(adapter)) {
            return knownObjects.get(adapter);
        }

        boolean withCompleteData = resolveState == ResolveState.TRANSIENT || resolveState == ResolveState.RESOLVED;

        final String type = adapter.getSpecification().getFullName();
        final Oid oid = adapter.getOid();
        final ObjectData data = factory.createObjectData(type, oid, withCompleteData, adapter.getVersion());
        if (isTransient) {
            knownObjects.put(adapter, data);
        }

        final NakedObjectAssociation[] fields = dataStructure.getFields(adapter.getSpecification());
        final Data[] fieldContent = new Data[fields.length];
        PersistorUtil.start(adapter, adapter.getResolveState().serializeFrom());
        for (int i = 0; i < fields.length; i++) {
            if (!fields[i].isPersisted()) {
                continue;
            }
            final NakedObject field = fields[i].get(adapter);

            if (fields[i].getSpecification().isEncodeable()) {
                if (field == null) {
                    fieldContent[i] = factory.createNullData(fields[i].getSpecification().getFullName());
                } else {
                    fieldContent[i] = serializeEncodeable(factory, field);
                }

            } else if (fields[i].isOneToManyAssociation()) {
                fieldContent[i] = serializeCollection(factory, field, graphDepth - 1, knownObjects);

            } else if (fields[i].isOneToOneAssociation()) {
                if (field == null) {
                    fieldContent[i] = !withCompleteData ? null : factory.createNullData(fields[i].getSpecification()
                            .getFullName());
                } else {
                    fieldContent[i] = serializeObject2(factory, field, graphDepth - 1, knownObjects);
                }

            } else {
                throw new UnknownTypeException(fields[i]);
            }
        }
        PersistorUtil.end(adapter);
        data.setFieldContent(fieldContent);
        return data;
    }

    public void setDataStructure(final ObjectEncoderDataStructure dataStructure) {
        this.dataStructure = dataStructure;
    }

}
// Copyright (c) Naked Objects Group Ltd.




© 2015 - 2025 Weber Informatics LLC | Privacy Policy