def createOobMessage(self, domainValues):
        """Encode a list of objects into a self-contained message that can be used for
        out-of-band communication.
        """
        state = RequestState(self._service)

        encodedValues = list()
        for domainValue in domainValues:
            if domainValue is None:
                clientValue = None
            else:
                clientType = self._service.resolveClientType(
                        domainValue.__class__, BaseProxy, True)
                clientValue = state.getResolver().resolveClientValue(
                        domainValue, clientType, set())
            encodedValues.append(EntityCodex.encode(state, clientValue))

        map_ = IdToEntityMap()
        map_.update(state.beans)
        operations = list()
        self.createReturnOperations(operations, state, map_)

        invocation = FACTORY.invocation().as_()
        invocation.setParameters(encodedValues)

        bean = FACTORY.request()
        resp = bean.as_()
        resp.setInvocations(list(invocation))
        resp.setOperations(operations)
        return AutoBeanCodex.encode(bean)
 def visitReferenceProperty(self, propertyName, value, ctx):
     # containsKey to distinguish null from unknown
     if propertyName in self._flatValueMap:
         elementType = ctx.getElementType() if isinstance(ctx, CollectionPropertyContext) else None
         newValue = EntityCodex.decode(self._state, ctx.getType(),
                 elementType, self._flatValueMap[propertyName])
         resolved = self._state.getResolver().resolveDomainValue(newValue, False)
         self._procesor._service.setProperty(self._domain, propertyName,
                 self._procesor._service.resolveDomainClass(ctx.getType()), resolved)
     return False
    def decodeInvocationArguments(self, source, parameters, contextArgs,
            genericArgs):
        """Handles instance invocations as the instance at the 0th parameter.
        """
        if parameters is None:
            # Can't return Collections.emptyList() because this must be mutable
            return list()

        assert len(parameters) == contextArgs.length
        args = list()
        for i in range(contextArgs.length):
            type_ = contextArgs[i]
            elementType = None
            if Collection.isAssignableFrom(type_):
                elementType = TypeUtils.ensureBaseType(TypeUtils.getSingleParameterization(Collection, genericArgs[i]))
                split = parameters.get(i)
            else:
                split = parameters.get(i)
            arg = EntityCodex.decode(source, type_, elementType, split)
            arg = source.getResolver().resolveDomainValue(arg, not (EntityProxyId == contextArgs[i]))
            args.add(arg)
        return args
    def createReturnOperations(self, operations, returnState, toProcess):
        for id_, bean in toProcess.iteritems():
            domainObject = bean.getTag(Constants.DOMAIN_OBJECT)
            if id_.isEphemeral() and returnState.isEntityType(id_.getProxyClass()):
                # See if the entity has been persisted in the meantime
                returnState.getResolver().resolveClientValue(domainObject,
                        id_.getProxyClass(), set())

            if (id_.isEphemeral() or id_.isSynthetic()) or (domainObject is None):
                # If the object isn't persistent, there's no reason to send an update
                writeOperation = None
            elif not self._service.isLive(domainObject):
                writeOperation = WriteOperation.DELETE
            elif id_.wasEphemeral():
                writeOperation = WriteOperation.PERSIST
            else:
                writeOperation = WriteOperation.UPDATE

            version = None
            if ((writeOperation == WriteOperation.PERSIST)
                    or (writeOperation == WriteOperation.UPDATE)):
                # If we're sending an operation, the domain object must be persistent.
                # This means that it must also have a non-null version.
                domainVersion = self._service.getVersion(domainObject)
                if domainVersion is None:
                    raise UnexpectedException('The persisted entity with id '
                            + self._service.getId(domainObject)
                            + ' has a null version', None)
                version = returnState.flatten(domainVersion)

            inResponse = bean.getTag(Constants.IN_RESPONSE) is not None

            # Don't send any data back to the client for an update on an object that
            # isn't part of the response payload when the client's version matches
            # the domain version.
            if WriteOperation.UPDATE == writeOperation and not inResponse:
                previousVersion = bean.getTag(Constants.VERSION_PROPERTY_B64)
                if (version is not None and previousVersion is not None
                        and version == fromBase64(previousVersion)):
                    continue

            op = FACTORY.operation().as_()

            # Send a client id if the id is ephemeral or was previously associated
            # with a client id.
            if id_.wasEphemeral():
                op.setClientId(id_.getClientId())

            op.setOperation(writeOperation)

            # Only send properties for entities that are part of the return graph
            if inResponse:
                propertyMap = OrderedDict()
                # Add all non-null properties to the serialized form
                diff = AutoBeanUtils.getAllProperties(bean)
                for d in diff.iteritems():
                    value = d[1]
                    if value is not None:
                        propertyMap[d[0]] = EntityCodex.encode(returnState, value)
                op.setPropertyMap(propertyMap)

            if not id_.isEphemeral() and not id_.isSynthetic():
                # Send the server address only for persistent objects
                op.setServerId(toBase64(id_.getServerId()))

            if id_.isSynthetic():
                op.setStrength(Strength.SYNTHETIC)
                op.setSyntheticId(id_.getSyntheticId())
            elif id_.isEphemeral():
                op.setStrength(Strength.EPHEMERAL)

            op.setTypeToken(self._service.resolveTypeToken(id_.getProxyClass()))

            if version is not None:
                op.setVersion(toBase64(version.getPayload()))

            operations.add(op)
            invocationResults.append(domainReturnValue)
            successes.append(ok)
        contextMethodIt = contextMethods
        objects = invocationResults
        for i, success in enumerate(successes):
            assert len(contextMethodIt) > i
            assert len(objects) > i
            contextMethod = contextMethodIt[i]
            returnValue = objects[i]
            if success:
                # Convert domain object to client object
                requestReturnType = self._service.getRequestReturnType(contextMethod)
                returnValue = state.getResolver().resolveClientValue(returnValue,
                        requestReturnType, allPropertyRefs[returnValue])
                # Convert the client object to a string
                results.append(EntityCodex.encode(returnState, returnValue))
            else:
                results.append(returnValue)


    def processOperationMessages(self, state, req):
        operations = req.getOperations()
        if operations is None:
            return

        beans = state.getBeansForPayload(operations)
        assert len(operations) == len(beans)

        itOp = operations
        for bean in beans:
            operation = itOp.next()