AutoBean<T> clone = toClone.getFactory().create(toClone.getType()); clone.setTag(STABLE_ID, toClone.getTag(STABLE_ID)); clone.setTag(Constants.VERSION_PROPERTY_B64, toClone.getTag(Constants.VERSION_PROPERTY_B64)); clone.accept(new AutoBeanVisitor() { final Map<String, Object> values = AutoBeanUtils.getAllProperties(toClone);
/** * Take ownership of a proxy instance and make it editable. */ public <T extends BaseProxy> T editProxy(T object) { AutoBean<T> bean = checkStreamsNotCrossed(object); checkLocked(); @SuppressWarnings("unchecked") AutoBean<T> previouslySeen = (AutoBean<T>) state.editedProxies.get(BaseProxyCategory.stableId(bean)); if (previouslySeen != null && !previouslySeen.isFrozen()) { /* * If we've seen the object before, it might be because it was passed in as a method argument. * This does not guarantee its mutability, so check that here before returning the cached * object. */ return previouslySeen.as(); } // Create editable copies AutoBean<T> parent = bean; bean = cloneBeanAndCollections(bean); bean.setTag(Constants.PARENT_OBJECT, parent); return bean.as(); }
/** * Make an EntityProxy immutable. */ private void makeImmutable(final AutoBean<? extends BaseProxy> toMutate) { // Always diff'ed against itself, producing a no-op toMutate.setTag(Constants.PARENT_OBJECT, toMutate); // Act with entity-identity semantics toMutate.setTag(REQUEST_CONTEXT_STATE, null); toMutate.setFrozen(true); }
@Override public boolean visitReferenceProperty(String propertyName, AutoBean<?> value, PropertyContext ctx) { toReturn.put(propertyName, value == null ? null : value.as()); return false; }
OperationMessage operation = itOp.next(); bean.setTag(Constants.VERSION_PROPERTY_B64, operation.getVersion()); final Object domain = bean.getTag(Constants.DOMAIN_OBJECT); if (domain != null) { bean.accept(new AutoBeanVisitor() { @Override public boolean visitReferenceProperty(String propertyName, AutoBean<?> value,
public void decodeInto(EncodeState state, Splittable data, AutoBean<?> bean) { this.data = data; this.state = state; bean.accept(this); }
/** * This method checks that a proxy object is either immutable, or already edited by this context. */ private <T> AutoBean<T> checkStreamsNotCrossed(T object) { AutoBean<T> bean = AutoBeanUtils.getAutoBean(object); if (bean == null) { // Unexpected; some kind of foreign implementation? throw new IllegalArgumentException(object.getClass().getName()); } State otherState = bean.getTag(REQUEST_CONTEXT_STATE); if (!bean.isFrozen() && otherState != this.state) { /* * This means something is way off in the weeds. If a bean is editable, it's supposed to be * associated with a RequestContext. */ assert otherState != null : "Unfrozen bean with null RequestContext"; /* * Already editing the object in another context or it would have been in the editing map. */ throw new IllegalArgumentException("Attempting to edit an EntityProxy" + " previously edited by another RequestContext"); } return bean; }
/** * Effectively overrides {@link BaseProxyCategory#stableId(AutoBean)} to * return a narrower bound. */ public static <T extends EntityProxy> SimpleEntityProxyId<T> stableId( AutoBean<? extends T> bean) { return bean.getTag(STABLE_ID); }
/** * Copy data from a {@link Splittable} into an AutoBean. Unset values in the * Splittable will not nullify data that already exists in the AutoBean. * * @param data the source data to copy * @param bean the target AutoBean */ public static void decodeInto(Splittable data, AutoBean<?> bean) { AutoBeanCodexImpl.doDecodeInto(EncodeState.forDecode(bean.getFactory()), data, bean); }
private static String key(AutoBean<?> bean, String propertyName) { return bean.getType().getName() + ":" + propertyName; } }
/** * Creates an AutoBean for the given id, tracking a domain object. */ private <Q extends BaseProxy> AutoBean<Q> createProxyBean(SimpleProxyId<Q> id, Object domainObject) { AutoBean<Q> toReturn = AutoBeanFactorySource.createBean(id.getProxyClass(), SimpleRequestProcessor.CONFIGURATION); toReturn.setTag(Constants.STABLE_ID, id); toReturn.setTag(Constants.DOMAIN_OBJECT, domainObject); beans.put(id, toReturn); return toReturn; }
/** * Set the frozen status of all EntityProxies owned by this context. */ private void freezeEntities(boolean frozen) { for (AutoBean<?> bean : state.editedProxies.values()) { bean.setFrozen(frozen); } }
public Object key(Object object) { if (object instanceof EntityProxy) { return ((EntityProxy) object).stableId(); } else if (object instanceof ValueProxy) { AutoBean<?> bean = AutoBeanUtils.getAutoBean(object); // Possibly replace an editable ValueProxy with its immutable base AutoBean<?> parent = bean.getTag(Constants.PARENT_OBJECT); if (parent != null) { object = parent.as(); } return new ValueProxyHolder((ValueProxy) object); } return null; } };
private boolean equal(String propertyName, AutoBean<?> previousValue) { return previousValue == null && toReturn.get(propertyName) == null || previousValue != null && equal(propertyName, previousValue.as()); }