/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.internal.sessions.remote; import java.util.*; import org.eclipse.persistence.indirection.*; import org.eclipse.persistence.mappings.*; import org.eclipse.persistence.internal.descriptors.*; import org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder; /** * Helper class for RemoteSessionController. * This descriptor iterator will replace all the normal * value holders in an object with remote value holders * that can be serialized to the client. */ public class ReplaceValueHoldersIterator extends DescriptorIterator { RemoteSessionController controller; /** * default constructor */ private ReplaceValueHoldersIterator() { super(); } /** * public constructor */ public ReplaceValueHoldersIterator(RemoteSessionController controller) { this(); this.initialize(controller); } /** * build and return an object descriptor for the specified object */ protected ObjectDescriptor buildObjectDescriptor(Object object) { return controller.buildObjectDescriptor(object); } /** * build a properly initialized remote value holder */ protected RemoteValueHolder buildRemoteValueHolderFor(ValueHolderInterface valueHolder) { RemoteValueHolder remoteValueHolder = null; if (valueHolder instanceof RemoteValueHolder) { remoteValueHolder = (RemoteValueHolder)valueHolder; } else if ((valueHolder instanceof UnitOfWorkValueHolder) && ((UnitOfWorkValueHolder)valueHolder).getWrappedValueHolder() instanceof RemoteValueHolder) { return (RemoteValueHolder)((UnitOfWorkValueHolder)valueHolder).getWrappedValueHolder(); } else { remoteValueHolder = new RemoteValueHolder(); remoteValueHolder.setWrappedServerValueHolder(valueHolder); remoteValueHolder.setMapping(this.getCurrentMapping()); } saveRemoteValueHolder(remoteValueHolder); return remoteValueHolder; } /** * initialize instance */ protected void initialize(RemoteSessionController controller) { this.controller = controller; } /** * Iterate an indirect container. */ protected void internalIterateIndirectContainer(IndirectContainer container) { ValueHolderInterface containedValueHolder = container.getValueHolder(); if (containedValueHolder instanceof RemoteValueHolder) { containedValueHolder = ((RemoteValueHolder)containedValueHolder).getWrappedServerValueHolder(); } synchronized (containedValueHolder) { // extract VH within sync block to ensure correct one is used. ValueHolderInterface valueHolder = container.getValueHolder(); RemoteValueHolder remoteValueHolder = buildRemoteValueHolderFor(valueHolder); container.setValueHolder(remoteValueHolder); remoteValueHolder.setServerIndirectionObject(container); } } /** * Synchronously create a remote value holder. The value holder passed in is ignored * so that we can ensure that the value holder being held by the object is used * instead of the one that was passed in. */ protected void internalIterateValueHolder(ValueHolderInterface originalValueHolder) { ValueHolderInterface rootValueHolder = originalValueHolder; // Ensure we have the base server side value holder. There will only be one of these per server. if (rootValueHolder instanceof RemoteValueHolder) { rootValueHolder = ((RemoteValueHolder)rootValueHolder).getWrappedServerValueHolder(); } synchronized (rootValueHolder) { ValueHolderInterface valueHolder = (ValueHolderInterface)getCurrentMapping().getAttributeValueFromObject(getVisitedParent()); RemoteValueHolder remoteValueHolder = buildRemoteValueHolderFor(valueHolder); if (valueHolder != remoteValueHolder) { if (this.getCurrentMapping().isOneToOneMapping()) { this.setOneToOneMappingSettingsIn(remoteValueHolder); } this.getCurrentMapping().setAttributeValueInObject(this.getVisitedParent(), remoteValueHolder); } } } /** * if we get here, it is a domain object */ protected void iterate(Object object) { ((Map)getResult()).put(object, this.buildObjectDescriptor(object)); } /** * save the remote value holder for later use */ protected void saveRemoteValueHolder(RemoteValueHolder remoteValueHolder) { controller.saveRemoteValueHolder(remoteValueHolder); } /** * Set one-to-one mapping information. * This allows us to look for a cache hit * before going to the database. */ protected void setOneToOneMappingSettingsIn(RemoteValueHolder remoteValueHolder) { ObjectReferenceMapping oneToOneMapping = (ObjectReferenceMapping)this.getCurrentMapping();// cast it if (oneToOneMapping.getDescriptor().getObjectBuilder().isPrimaryKeyMapping(oneToOneMapping)) { remoteValueHolder.setRow(oneToOneMapping.extractPrimaryKeyRowForSourceObject(this.getVisitedParent(), this.getSession())); } remoteValueHolder.setTargetObjectPrimaryKeys(oneToOneMapping.extractPrimaryKeysForReferenceObject(this.getVisitedParent(), this.getSession())); } }