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()