
org.nakedobjects.plugins.remoting.shared.ObjectEncoderImpl Maven / Gradle / Ivy
package org.nakedobjects.plugins.remoting.shared;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.nakedobjects.metamodel.adapter.NakedObject;
import org.nakedobjects.metamodel.adapter.ResolveState;
import org.nakedobjects.metamodel.adapter.oid.Oid;
import org.nakedobjects.metamodel.adapter.version.Version;
import org.nakedobjects.metamodel.commons.ensure.Assert;
import org.nakedobjects.metamodel.commons.exceptions.UnknownTypeException;
import org.nakedobjects.metamodel.criteria.InstancesCriteria;
import org.nakedobjects.metamodel.facets.collections.modify.CollectionFacet;
import org.nakedobjects.metamodel.spec.NakedObjectSpecification;
import org.nakedobjects.metamodel.spec.feature.NakedObjectAssociation;
import org.nakedobjects.metamodel.util.CollectionFacetUtils;
import org.nakedobjects.plugins.remoting.shared.data.ClientActionResultData;
import org.nakedobjects.plugins.remoting.shared.data.CollectionData;
import org.nakedobjects.plugins.remoting.shared.data.CriteriaData;
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.IdentityData;
import org.nakedobjects.plugins.remoting.shared.data.KnownObjects;
import org.nakedobjects.plugins.remoting.shared.data.NullData;
import org.nakedobjects.plugins.remoting.shared.data.ObjectData;
import org.nakedobjects.plugins.remoting.shared.data.ReferenceData;
import org.nakedobjects.plugins.remoting.shared.data.ServerActionResultData;
import org.nakedobjects.runtime.context.NakedObjectsContext;
import org.nakedobjects.runtime.persistence.PersistorUtil;
public class ObjectEncoderImpl implements ObjectEncoder {
private final ObjectEncoderSerializer encoder = new ObjectEncoderSerializer();
private final ObjectEncoderDeserializer decoder = new ObjectEncoderDeserializer();
private final ObjectEncoderDataStructure dataStructure = new ObjectEncoderDataStructure();
private final Map criteriaStragies = new HashMap();
private DataFactory factory;
private int actionGraphDepth = 0;
private int persistentGraphDepth = 100;
private int updateGraphDepth = 1;
{
encoder.setDataStructure(dataStructure);
decoder.setDataStructure(dataStructure);
addCriteriaStrategy(new CriteriaEncoderAllInstances());
addCriteriaStrategy(new CriteriaEncoderFindByTitle());
addCriteriaStrategy(new CriteriaEncoderPattern());
}
public void addCriteriaStrategy(final CriteriaEncoder encoder) {
criteriaStragies.put(encoder.getCriteriaClass(), encoder);
}
public ReferenceData createActionTarget(final NakedObject target, final KnownObjects knownObjects) {
return encoder.serializeObject(factory, target, actionGraphDepth, knownObjects);
}
public ClientActionResultData createClientActionResult(
final ReferenceData[] madePersistent,
final Version[] changedVersion,
final ObjectData[] updates) {
return factory.createClientActionResultData(madePersistent, changedVersion, updates);
}
public final ObjectData createCompletePersistentGraph(final NakedObject object) {
return (ObjectData) encoder.serializeObject(factory, object, persistentGraphDepth, new KnownObjects());
}
public CriteriaData createCriteriaData(final InstancesCriteria criteria) {
final CriteriaEncoder strategy = findCriteriaEncoder(criteria.getClass());
return strategy.createData(criteria, this);
}
public Data createForResolveField(final NakedObject adapter, final String fieldName) {
final Oid oid = adapter.getOid();
final NakedObjectSpecification specification = adapter.getSpecification();
final String type = specification.getFullName();
final ResolveState resolveState = adapter.getResolveState();
Data[] fieldContent;
final NakedObjectAssociation[] fields = getFieldOrder(specification);
fieldContent = new Data[fields.length];
PersistorUtil.start(adapter, adapter.getResolveState().serializeFrom());
final KnownObjects knownObjects = new KnownObjects();
for (int i = 0; i < fields.length; i++) {
if (fields[i].getId().equals(fieldName)) {
final NakedObject field = fields[i].get(adapter);
if (field == null) {
fieldContent[i] = factory.createNullData(fields[i].getSpecification().getFullName());
} else if (fields[i].getSpecification().isEncodeable()) {
fieldContent[i] = encoder.serializeEncodeable(factory, field);
} else if (fields[i].isOneToManyAssociation()) {
fieldContent[i] = encoder.serializeCollection(factory, field, persistentGraphDepth, knownObjects);
} else {
NakedObjectsContext.getPersistenceSession().resolveImmediately(field);
fieldContent[i] = encoder.serializeObject(factory, field, persistentGraphDepth, knownObjects);
}
break;
}
}
PersistorUtil.end(adapter);
// TODO remove the fudge - needed as collections are part of parents, hence parent object gets set as
// resolving (is not a ghost) yet it has no version number
// return createObjectData(oid, type, fieldContent, resolveState.isResolved(),
// !resolveState.isGhost(), object.getVersion());
final ObjectData data = factory.createObjectData(type, oid, resolveState.isResolved(), adapter.getVersion());
data.setFieldContent(fieldContent);
return data;
// return createObjectData(oid, type, fieldContent, resolveState.isResolved(), object.getVersion());
}
public ObjectData createForUpdate(final NakedObject object) {
final ResolveState resolveState = object.getResolveState();
if (resolveState.isSerializing() || resolveState.isGhost()) {
throw new NakedObjectsRemoteException("Illegal resolve state: " + object);
}
return (ObjectData) encoder.serializeObject(factory, object, updateGraphDepth, new KnownObjects());
}
public ObjectData createGraphForChangedObject(final NakedObject object, final KnownObjects knownObjects) {
return (ObjectData) encoder.serializeObject(factory, object, 1, knownObjects);
}
/**
* Creates a ReferenceData that contains the type, version and OID for the specified object. This can only
* be used for persistent objects.
*/
public final IdentityData createIdentityData(final NakedObject object) {
Assert.assertNotNull("OID needed for reference", object, object.getOid());
return factory.createIdentityData(object.getSpecification().getFullName(), object.getOid(), object.getVersion());
}
private Data createMadePersistentCollection(final CollectionData collectionData, final NakedObject collection) {
final ReferenceData[] elementData = collectionData.getElements();
final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(collection);
final Iterator elements = facet.iterator(collection);
for (int i = 0; i < elementData.length; i++) {
final NakedObject element = (NakedObject) elements.next();
final Oid oid = element.getOid();
Assert.assertNotNull(oid);
elementData[i] = createMadePersistentGraph((ObjectData) elementData[i], element);
}
return collectionData;
}
public ObjectData createMadePersistentGraph(final ObjectData data, final NakedObject object) {
final Oid objectsOid = object.getOid();
Assert.assertNotNull(objectsOid);
if (objectsOid.hasPrevious()) {
final Version version = object.getVersion();
final String type = data.getType();
final ObjectData persistedData = factory.createObjectData(type, objectsOid, true, version);
final Data[] allContents = data.getFieldContent();
if (allContents != null) {
final int contentLength = allContents.length;
final Data persistentContents[] = new Data[contentLength];
final NakedObjectAssociation[] fields = getFieldOrder(object.getSpecification());
for (int i = 0; i < contentLength; i++) {
final Data fieldData = allContents[i];
if (fieldData instanceof NullData) {
persistentContents[i] = null;
} else if (fields[i].isOneToOneAssociation()) {
if (fieldData instanceof ObjectData) {
final NakedObject fieldReference = fields[i].get(object);
persistentContents[i] = createMadePersistentGraph((ObjectData) fieldData, fieldReference);
} else {
persistentContents[i] = null;
}
} else if (fields[i].isOneToManyAssociation()) {
final NakedObject fieldReference = fields[i].get(object);
persistentContents[i] = createMadePersistentCollection((CollectionData) fieldData, fieldReference);
}
}
persistedData.setFieldContent(persistentContents);
}
return persistedData;
} else {
return null;
}
}
public ObjectData createMakePersistentGraph(final NakedObject adapter, final KnownObjects knownObjects) {
Assert.assertTrue("transient", adapter.isTransient());
return (ObjectData) encoder.serializeObject(factory, adapter, 1, knownObjects);
}
private final Data createParameter(final String type, final NakedObject object, final KnownObjects knownObjects) {
if (object == null) {
return factory.createNullData(type);
}
if (object.getSpecification().isObject()) {
if (object.getSpecification().isEncodeable()) {
return encoder.serializeEncodeable(factory, object);
} else {
final NakedObject nakedObject = object;
return encoder.serializeObject(factory, nakedObject, 0, knownObjects);
}
} else {
throw new UnknownTypeException(object.getSpecification());
}
}
public final Data[] createParameters(
final NakedObjectSpecification[] parameterTypes,
final NakedObject[] parameters,
final KnownObjects knownObjects) {
final Data parameterData[] = new Data[parameters.length];
for (int i = 0; i < parameters.length; i++) {
final NakedObject parameter = parameters[i];
final String type = parameterTypes[i].getFullName();
parameterData[i] = createParameter(type, parameter, knownObjects);
}
return parameterData;
}
public ServerActionResultData createServerActionResult(
final NakedObject result,
final ObjectData[] updates,
final ReferenceData[] disposed,
final ObjectData persistedTarget,
final ObjectData[] persistedParameters,
final String[] messages,
final String[] warnings) {
Data result1;
if (result == null) {
result1 = factory.createNullData("");
} else if (result.getSpecification().isCollection()) {
result1 = encoder.serializeCollection(factory, result, persistentGraphDepth, new KnownObjects());
} else if (result.getSpecification().isObject()) {
result1 = createCompletePersistentGraph(result);
} else {
throw new UnknownTypeException(result);
}
return factory.createServerActionResultData(result1, updates, disposed, persistedTarget, persistedParameters, messages,
warnings);
}
public EncodeableObjectData createValue(final NakedObject value) {
return encoder.serializeEncodeable(factory, value);
}
public ObjectData createObject(final NakedObject object) {
return (ObjectData) encoder.serializeObject(factory, object, 0, new KnownObjects());
}
public NakedObjectAssociation[] getFieldOrder(final NakedObjectSpecification specification) {
return dataStructure.getFields(specification);
}
public void madePersistent(final NakedObject target, final ObjectData persistedTarget) {
decoder.madePersistent(target, persistedTarget);
}
public NakedObject restore(final Data data) {
return decoder.restore(data);
}
public NakedObject restore(final Data data, final KnownObjects knownObjects) {
return decoder.restore(data, knownObjects);
}
public InstancesCriteria restoreCriteria(final CriteriaData criteriaData) {
final Class> criteriaClass = criteriaData.getCriteriaClass();
final CriteriaEncoder strategy = findCriteriaEncoder(criteriaClass);
return strategy.restore(criteriaData, this);
}
private CriteriaEncoder findCriteriaEncoder(final Class> criteriaClass) {
final CriteriaEncoder strategy = (CriteriaEncoder) criteriaStragies.get(criteriaClass);
if (strategy == null) {
throw new NakedObjectsRemoteException("No encoding strategy for " + criteriaClass.getName());
}
return strategy;
}
/**
* .NET property
*
* @property
* @see #setActionGraphDepth(int)
*/
public void set_ActionGraphDepth(final int actionGraphDepth) {
setActionGraphDepth(actionGraphDepth);
}
/**
* .NET property
*
* @property
* @see #setPersistentGraphDepth(int)
*/
public void set_PersistentGraphDepth(final int persistentGraphDepth) {
setPersistentGraphDepth(persistentGraphDepth);
}
/**
* .NET property
*
* @property
* @see #setUpdateGraphDepth(int)
*/
public void set_UpdateGraphDepth(final int updateGraphDepth) {
setUpdateGraphDepth(updateGraphDepth);
}
/**
* Specifies the maximum depth to recurse when creating data graphs for the method
* createDataForActionTarget. Defaults to 100.
*/
public void setActionGraphDepth(final int actionGraphDepth) {
this.actionGraphDepth = actionGraphDepth;
}
/**
* .NET property
*
* @property
*/
public void set_DataFactory(final DataFactory factory) {
setDataFactory(factory);
}
public void setDataFactory(final DataFactory factory) {
this.factory = factory;
}
/**
* Specifies the maximum depth to recurse when creating data graphs of persistent objects. Defaults to
* 100.
*/
public void setPersistentGraphDepth(final int persistentGraphDepth) {
this.persistentGraphDepth = persistentGraphDepth;
}
/**
* Specifies the maximum depth to recurse when creating data graphs for updates. Defaults to 1.
*/
public void setUpdateGraphDepth(final int updateGraphDepth) {
this.updateGraphDepth = updateGraphDepth;
}
}
// Copyright (c) Naked Objects Group Ltd.
© 2015 - 2025 Weber Informatics LLC | Privacy Policy