Example #1
0
 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
Example #2
0
    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
Example #3
0
 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
Example #4
0
    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
Example #6
0
    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
Example #7
0
    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()
Example #8
0
    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()
Example #9
0
    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