Package org.apache.isis.runtimes.dflt.remoting.protocol.internal

Source Code of org.apache.isis.runtimes.dflt.remoting.protocol.internal.ObjectSerializer

/*
*  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.apache.isis.runtimes.dflt.remoting.protocol.internal;

import java.util.Enumeration;

import org.apache.isis.core.commons.ensure.Assert;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.exceptions.UnknownTypeException;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.ResolveState;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacet;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.runtimes.dflt.remoting.common.data.Data;
import org.apache.isis.runtimes.dflt.remoting.common.data.DataFactory;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.CollectionData;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.EncodableObjectData;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.ObjectData;
import org.apache.isis.runtimes.dflt.remoting.common.data.common.ReferenceData;
import org.apache.isis.runtimes.dflt.remoting.common.exchange.KnownObjectsRequest;
import org.apache.isis.runtimes.dflt.runtime.persistence.PersistorUtil;

/**
* Utility class to create Data objects representing a graph of Isis.
*
* As each object is serialised its resolved state is changed to SERIALIZING;
* any object that is marked as SERIALIZING is skipped.
*/
public final class ObjectSerializer {

    private final DataFactory dataFactory;
    private final FieldOrderCache fieldOrderCache;

    public ObjectSerializer(final DataFactory dataFactory, final FieldOrderCache fieldOrderCache) {
        this.fieldOrderCache = fieldOrderCache;
        this.dataFactory = dataFactory;
    }

    public final ReferenceData serializeAdapter(final ObjectAdapter adapter, final int depth, final KnownObjectsRequest knownObjects) {
        Assert.assertNotNull(adapter);
        return (ReferenceData) serializeObject2(adapter, depth, knownObjects);
    }

    public final EncodableObjectData serializeEncodeable(final ObjectAdapter adapter) {
        final EncodableFacet facet = adapter.getSpecification().getFacet(EncodableFacet.class);
        return this.dataFactory.createValueData(adapter.getSpecification().getFullIdentifier(), facet.toEncodedString(adapter));
    }

    private final Data serializeObject2(final ObjectAdapter adapter, final int graphDepth, final KnownObjectsRequest knownObjects) {
        Assert.assertNotNull(adapter);

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

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

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

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

        final ObjectAssociation[] fields = fieldOrderCache.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].isNotPersisted()) {
                continue;
            }
            final ObjectAdapter field = fields[i].get(adapter);

            if (fields[i].getSpecification().isEncodeable()) {
                if (field == null) {
                    fieldContent[i] = this.dataFactory.createNullData(fields[i].getSpecification().getFullIdentifier());
                } else {
                    fieldContent[i] = serializeEncodeable(field);
                }

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

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

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

    public CollectionData serializeCollection(final ObjectAdapter collectionAdapter, final int graphDepth, final KnownObjectsRequest knownObjects) {
        final Oid oid = collectionAdapter.getOid();
        final String collectionType = collectionAdapter.getSpecification().getFullIdentifier();
        final TypeOfFacet typeOfFacet = collectionAdapter.getSpecification().getFacet(TypeOfFacet.class);
        if (typeOfFacet == null) {
            throw new IsisException("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 ObjectAdapter element = (ObjectAdapter) e.nextElement();
                elements[i++] = serializeAdapter(element, graphDepth, knownObjects);
            }
        } else {
            elements = new ObjectData[0];
        }

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

}
TOP

Related Classes of org.apache.isis.runtimes.dflt.remoting.protocol.internal.ObjectSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.