def flatten(self, domainValue): """Turn a domain value into a wire format message.""" if ValueCodex.canDecode(domainValue.getClass()): flatValue = ValueCodex.encode(domainValue) else: flatValue = SimpleRequestProcessor(self._service).createOobMessage([domainValue]) return flatValue
def getBeansForIds(self, ids): """Returns the AutoBeans corresponding to the given ids, or creates them if they do not yet exist. """ domainClasses = list() domainIds = list() idsToLoad = list() # Create proxies for ephemeral or synthetic ids that we haven't seen. Queue # up the domain ids for entities that need to be loaded. for id_ in ids: domainClass = self._service.resolveDomainClass(id_.getProxyClass()) if id_ in self.beans: # Already have a proxy for this id, no-op pass elif id_.isEphemeral() or id_.isSynthetic(): # Create a new domain object for the short-lived id domain = self._service.createDomainObject(domainClass) if domain is None: raise UnexpectedException('Could not create instance of ' + domainClass.getCanonicalName(), None) bean = self.createProxyBean(id_, domain) self.beans[id_] = bean self._domainObjectsToId[domain] = id_ else: # Decode the domain parameter split = StringQuoter.split(id_.getServerId()) param = self._service.getIdType(domainClass) if ValueCodex.canDecode(param): domainParam = ValueCodex.decode(param, split) else: domainParam = SimpleRequestProcessor(self._service).decodeOobMessage(param, split).get(0) # Enqueue domainClasses.append(self._service.resolveDomainClass(id_.getProxyClass())) domainIds.append(domainParam) idsToLoad.append(id_) # Actually load the data if len(domainClasses) > 0: assert (len(domainClasses) == len(domainIds) and len(domainClasses) == len(idsToLoad)) loaded = self._service.loadDomainObjects(domainClasses, domainIds) if len(idsToLoad) != len(loaded): raise UnexpectedException('Expected ' + len(idsToLoad) + ' objects to be loaded, got ' + len(loaded), None) itLoaded = iter(loaded) for id_ in idsToLoad: domain = itLoaded.next() self._domainObjectsToId[domain] = id_ bean = self.createProxyBean(id_, domain) self.beans[id_] = bean # Construct the return value toReturn = list() for id_ in ids: toReturn.append(self.beans.get(id_)) return toReturn
def flatten(self, domainValue): """Turn a domain value into a wire format message.""" if ValueCodex.canDecode(domainValue.getClass()): flatValue = ValueCodex.encode(domainValue) else: flatValue = SimpleRequestProcessor(self._service).createOobMessage( [domainValue]) return flatValue
def visitReferenceProperty(self, propertyName, value, ctx): # Send the property if the enclosing type is a ValueProxy, if the owner # requested the property, or if the property is a list of values. elementType = ctx.getElementType() if isinstance( ctx, CollectionPropertyContext) else None shouldSend = (self._isOwnerValueProxy or self._resolver.matchesPropertyRef( self._propertyRefs, propertyName)) or ( elementType is not None and ValueCodex.canDecode(elementType)) if not shouldSend: return False # Call the getter domainValue = self._resolver._service.getProperty( self._domainEntity, propertyName) if domainValue is None: return False # Turn the domain object into something usable on the client side if elementType is None: type_ = ctx.getType() else: type_ = CollectionType(ctx.getType(), elementType) resolution = self._resolver.resolveClientValue(domainValue, type_) self._resolver.addPathsToResolution(resolution, propertyName, self._propertyRefs) ctx.set(resolution.getClientObject()) return False
def visitValueProperty(self, propertyName, value, ctx): if propertyName in self._flatValueMap: split = self._flatValueMap[propertyName] newValue = ValueCodex.decode(ctx.getType(), split) resolved = self._state.getResolver().resolveDomainValue(newValue, False) self._procesor._service.setProperty(self._domain, propertyName, ctx.getType(), resolved) return False
def visitReferenceProperty(self, propertyName, value, ctx): # Send the property if the enclosing type is a ValueProxy, if the owner # requested the property, or if the property is a list of values. elementType = ctx.getElementType() if isinstance(ctx, CollectionPropertyContext) else None shouldSend = (self._isOwnerValueProxy or self._resolver.matchesPropertyRef(self._propertyRefs, propertyName)) or (elementType is not None and ValueCodex.canDecode(elementType)) if not shouldSend: return False # Call the getter domainValue = self._resolver._service.getProperty(self._domainEntity, propertyName) if domainValue is None: return False # Turn the domain object into something usable on the client side if elementType is None: type_ = ctx.getType() else: type_ = CollectionType(ctx.getType(), elementType) resolution = self._resolver.resolveClientValue(domainValue, type_) self._resolver.addPathsToResolution(resolution, propertyName, self._propertyRefs) ctx.set(resolution.getClientObject()) return False
def resolveClientValue(self, domainValue, clientTypeOrAssignableTo, propertyRefs=None): """Given a domain object, return a value that can be encoded by the client. Creates a Resolution object that holds a client value that represents the given domain value. The resolved client value will be assignable to {@code clientType}. @param domainValue the domain object to be converted into a client-side value @param assignableTo the type in the client to which the resolved value should be assignable. A value of {@code null} indicates that any resolution will suffice. @param propertyRefs the property references requested by the client """ if propertyRefs is None: clientType = clientTypeOrAssignableTo if domainValue is None: return Resolution(None) anyType = clientType is None if anyType: clientType = object() assignableTo = TypeUtils.ensureBaseType(clientType) key = ResolutionKey(domainValue, clientType) previous = self._resolved[key] if (previous is not None and assignableTo.isInstance(previous.getClientObject())): return previous returnClass = self._service.resolveClientType(domainValue.getClass(), assignableTo, True) if anyType: assignableTo = returnClass # Pass simple values through if ValueCodex.canDecode(returnClass): return self.makeResolution(domainValue) # Convert entities to EntityProxies or EntityProxyIds isProxy = BaseProxy.isAssignableFrom(returnClass) isId = issubclass(returnClass, EntityProxyId) if isProxy or isId: proxyClass = returnClass.asSubclass(BaseProxy) return self.resolveClientProxy(domainValue, proxyClass, key) # Convert collections if issubclass(returnClass, Collection): if issubclass(returnClass, list): accumulator = list() elif issubclass(returnClass, set): accumulator = set() else: raise ReportableException('Unsupported collection type' + returnClass.getName()) elementType = TypeUtils.getSingleParameterization(Collection, clientType) for o in domainValue: accumulator.add(self.resolveClientValue(o, elementType).getClientObject()) return self.makeResolution(accumulator) raise ReportableException('Unsupported domain type ' + returnClass.getCanonicalName()) else: assignableTo = clientTypeOrAssignableTo toReturn = self.resolveClientValue(domainValue, assignableTo) if toReturn is None: return None self.addPathsToResolution(toReturn, '', self.expandPropertyRefs(propertyRefs)) while len(self._toProcess) > 0: working = list(self._toProcess) self._toProcess.clear() for resolution in working: if resolution.hasWork(): bean = AutoBeanUtils.getAutoBean(resolution.getClientObject()) bean.accept(self.PropertyResolver(resolution)) return toReturn.getClientObject()
def resolveClientValue(self, domainValue, clientTypeOrAssignableTo, propertyRefs=None): """Given a domain object, return a value that can be encoded by the client. Creates a Resolution object that holds a client value that represents the given domain value. The resolved client value will be assignable to {@code clientType}. @param domainValue the domain object to be converted into a client-side value @param assignableTo the type in the client to which the resolved value should be assignable. A value of {@code null} indicates that any resolution will suffice. @param propertyRefs the property references requested by the client """ if propertyRefs is None: clientType = clientTypeOrAssignableTo if domainValue is None: return Resolution(None) anyType = clientType is None if anyType: clientType = object() assignableTo = TypeUtils.ensureBaseType(clientType) key = ResolutionKey(domainValue, clientType) previous = self._resolved[key] if (previous is not None and assignableTo.isInstance(previous.getClientObject())): return previous returnClass = self._service.resolveClientType( domainValue.getClass(), assignableTo, True) if anyType: assignableTo = returnClass # Pass simple values through if ValueCodex.canDecode(returnClass): return self.makeResolution(domainValue) # Convert entities to EntityProxies or EntityProxyIds isProxy = BaseProxy.isAssignableFrom(returnClass) isId = issubclass(returnClass, EntityProxyId) if isProxy or isId: proxyClass = returnClass.asSubclass(BaseProxy) return self.resolveClientProxy(domainValue, proxyClass, key) # Convert collections if issubclass(returnClass, Collection): if issubclass(returnClass, list): accumulator = list() elif issubclass(returnClass, set): accumulator = set() else: raise ReportableException('Unsupported collection type' + returnClass.getName()) elementType = TypeUtils.getSingleParameterization( Collection, clientType) for o in domainValue: accumulator.add( self.resolveClientValue(o, elementType).getClientObject()) return self.makeResolution(accumulator) raise ReportableException('Unsupported domain type ' + returnClass.getCanonicalName()) else: assignableTo = clientTypeOrAssignableTo toReturn = self.resolveClientValue(domainValue, assignableTo) if toReturn is None: return None self.addPathsToResolution(toReturn, '', self.expandPropertyRefs(propertyRefs)) while len(self._toProcess) > 0: working = list(self._toProcess) self._toProcess.clear() for resolution in working: if resolution.hasWork(): bean = AutoBeanUtils.getAutoBean( resolution.getClientObject()) bean.accept(self.PropertyResolver(resolution)) return toReturn.getClientObject()
def getBeansForIds(self, ids): """Returns the AutoBeans corresponding to the given ids, or creates them if they do not yet exist. """ domainClasses = list() domainIds = list() idsToLoad = list() # Create proxies for ephemeral or synthetic ids that we haven't seen. Queue # up the domain ids for entities that need to be loaded. for id_ in ids: domainClass = self._service.resolveDomainClass(id_.getProxyClass()) if id_ in self.beans: # Already have a proxy for this id, no-op pass elif id_.isEphemeral() or id_.isSynthetic(): # Create a new domain object for the short-lived id domain = self._service.createDomainObject(domainClass) if domain is None: raise UnexpectedException( 'Could not create instance of ' + domainClass.getCanonicalName(), None) bean = self.createProxyBean(id_, domain) self.beans[id_] = bean self._domainObjectsToId[domain] = id_ else: # Decode the domain parameter split = StringQuoter.split(id_.getServerId()) param = self._service.getIdType(domainClass) if ValueCodex.canDecode(param): domainParam = ValueCodex.decode(param, split) else: domainParam = SimpleRequestProcessor( self._service).decodeOobMessage(param, split).get(0) # Enqueue domainClasses.append( self._service.resolveDomainClass(id_.getProxyClass())) domainIds.append(domainParam) idsToLoad.append(id_) # Actually load the data if len(domainClasses) > 0: assert (len(domainClasses) == len(domainIds) and len(domainClasses) == len(idsToLoad)) loaded = self._service.loadDomainObjects(domainClasses, domainIds) if len(idsToLoad) != len(loaded): raise UnexpectedException( 'Expected ' + len(idsToLoad) + ' objects to be loaded, got ' + len(loaded), None) itLoaded = iter(loaded) for id_ in idsToLoad: domain = itLoaded.next() self._domainObjectsToId[domain] = id_ bean = self.createProxyBean(id_, domain) self.beans[id_] = bean # Construct the return value toReturn = list() for id_ in ids: toReturn.append(self.beans.get(id_)) return toReturn