/** * 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}. */ private Resolution resolveClientValue(Object domainValue, Type clientType) { if (domainValue == null) { return new Resolution(null); } boolean anyType = clientType == null; if (anyType) { clientType = Object.class; } Class<?> assignableTo = TypeUtils.ensureBaseType(clientType); ResolutionKey key = new ResolutionKey(domainValue, clientType); Resolution previous = resolved.get(key); if (previous != null && assignableTo.isInstance(previous.getClientObject())) { return previous; } Class<?> returnClass = service.resolveClientType(domainValue.getClass(), assignableTo, true); if (anyType) { assignableTo = returnClass; } // Pass simple values through if (ValueCodex.canDecode(returnClass)) { return makeResolution(domainValue); } // Convert entities to EntityProxies or EntityProxyIds boolean isProxy = BaseProxy.class.isAssignableFrom(returnClass); boolean isId = EntityProxyId.class.isAssignableFrom(returnClass); if (isProxy || isId) { Class<? extends BaseProxy> proxyClass = returnClass.asSubclass(BaseProxy.class); return resolveClientProxy(domainValue, proxyClass, key); } // Convert collections if (Collection.class.isAssignableFrom(returnClass)) { Collection<Object> accumulator; if (List.class.isAssignableFrom(returnClass)) { accumulator = new ArrayList<Object>(); } else if (Set.class.isAssignableFrom(returnClass)) { accumulator = new HashSet<Object>(); } else { throw new ReportableException("Unsupported collection type" + returnClass.getName()); } Type elementType = TypeUtils.getSingleParameterization(Collection.class, clientType); for (Object o : (Collection<?>) domainValue) { accumulator.add(resolveClientValue(o, elementType).getClientObject()); } return makeResolution(accumulator); } throw new ReportableException("Unsupported domain type " + returnClass.getCanonicalName()); }
@Override public boolean visitReferenceProperty( String propertyName, AutoBean<?> value, PropertyContext 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. */ Class<?> elementType = ctx instanceof CollectionPropertyContext ? ((CollectionPropertyContext) ctx).getElementType() : null; boolean shouldSend = isOwnerValueProxy || matchesPropertyRef(propertyRefs, propertyName) || elementType != null && ValueCodex.canDecode(elementType); if (!shouldSend) { return false; } // Call the getter Object domainValue = service.getProperty(domainEntity, propertyName); if (domainValue == null) { return false; } // Turn the domain object into something usable on the client side Type type; if (elementType == null) { type = ctx.getType(); } else { type = new CollectionType(ctx.getType(), elementType); } Resolution resolution = resolveClientValue(domainValue, type); addPathsToResolution(resolution, propertyName, propertyRefs); ctx.set(resolution.getClientObject()); return false; }