protected <Y> void parseInlineJson(X targetEntity, ErraiAttribute<? super X, Y> attr, JSONValue attrJsonValue, ErraiEntityManager eem) { Class<Y> attributeType = attr.getJavaType(); Y value; // FIXME this should search all managed types, or maybe all embeddables. not just entities. if (eem.getMetamodel().getEntities().contains(attributeType)) { ErraiIdentifiableType<Y> attrEntityType = eem.getMetamodel().entity(attributeType); value = attrEntityType.fromJson(eem, attrJsonValue); } else { value = JsonUtil.basicValueFromJson(attrJsonValue, attributeType); } attr.set(targetEntity, value); }
/** * Changes the ID of an existing entity in desiredStateEm. * * @param entityType The metamodel type for the entity whose ID is to be changed * @param oldId The ID that the entity currently has. * @param newId The ID that the entity will have when this method returns. */ private <E> void changeId(ErraiIdentifiableType<E> entityType, Object oldId, Object newId) { // XXX this routine is probably better handled internally by the ErraiEntityManager // TODO what about related entities that refer to this one? (needs tests) E entity = desiredStateEm.find(entityType.getJavaType(), oldId); desiredStateEm.remove(entity); desiredStateEm.flush(); desiredStateEm.detach(entity); entityType.getId(Object.class).set(entity, newId); desiredStateEm.persist(entity); }
@Override public List<X> getResultList() { List<X> results = em.findAll(em.getMetamodel().entity(resultType), this); Comparator<X> cmp = getComparator(); if (cmp != null) { Collections.sort(results, cmp); } return results; }
@Override public Long next(ErraiEntityManager entityManager) { while (entityManager.isKeyInUse(new Key<X, Long>((ErraiIdentifiableType<X>) attr.getDeclaringType(), nextCandidateId))) { nextCandidateId += (long) (Math.random() * probeJumpSize); // control rollover in case we run out of values if (nextCandidateId >= Long.MAX_VALUE - probeJumpSize) { nextCandidateId = 0; } } return nextCandidateId++; } }
@Override public Object getParameterValue(String name) { Parameter<?> parameter = getExistingParameter(name); return getParameterValue(parameter); }
@Override public Query createNamedQuery(final String name) { return createNamedQuery(name, Object.class); }
/** * Retrieves an ErraiEntityType by name rather than class reference. * * @param className * The fully-qualified class name of the entity type to retrieve (as * returned by {@code Class.getName()}). Null not permitted. * @return the ErraiEntityType associated with the named class. * @throws IllegalArgumentException * if the given class name is not an known entity type. */ public <X> ErraiEntityType<X> entity(String className) { return entity(className, true); }
@Override public <X, Y> Y get(Attribute<X, Y> attribute, X entity) { return ((ErraiAttribute<X, Y>) attribute).get(entity); }
@Override public Object getParameterValue(int position) { return getParameterValue(getParameter(position)); }
/** * Creates an EntityManager that knows about all the same managed types and * named queries as the given entity manager, but works from a different * storage backend. When combined with the namespacing support of a storage * backend, this allows you to work with several independent entity managers * at the same time. * * @param delegateEntityManager * @param namespacedStorageBackend */ public ErraiEntityManager(final ErraiEntityManager delegateEntityManager, final StorageBackendFactory namespacedStorageBackend) { this(delegateEntityManager.getMetamodel(), delegateEntityManager.namedQueries, namespacedStorageBackend); }
@Override public void flush() { // deferred backend operations not (yet!) implemented // persist updates to entities in the persistence context for (final Map.Entry<Key<?, ?>, Object> entry : persistenceContext.entrySet()) { // type safety warning should go away when we have a real PersistenceContext implementation updateInBackend((Key<Object, ?>) entry.getKey(), entry.getValue()); } }
@Override public <T> T merge(final T entity) { return applyCascadingOperation(entity, CascadeType.MERGE); }
/** * Clears all expected state and actual state data (essentially wiping out all * localStorage data that Errai cares about). This operation will destroy any * local data that has not been synced to the server, including data that the * sync manager was never told about. */ public void clear() { desiredStateEm.removeAll(); expectedStateEm.removeAll(); } }
/** * Returns true if this persistence context contains an entity retrievable by * the given key. The type matching is done in the same way as described in * {@link #get(Key)}. * * @param key * the identity of the entity to look for. Must not be null. * @return True if and only if this persistence context contains an entity * retrievable by the given key. */ public boolean contains(Key<?, ?> key) { return get(key) != null; }
@Override public Integer next(ErraiEntityManager entityManager) { while (entityManager.isKeyInUse(new Key<X, Integer>((ErraiIdentifiableType<X>) attr.getDeclaringType(), nextCandidateId))) { nextCandidateId += (int) (Math.random() * probeJumpSize); // control rollover in case we run out of values if (nextCandidateId >= Integer.MAX_VALUE - probeJumpSize) { nextCandidateId = 1; } } return nextCandidateId++; }
@Override public void persist(final Object entity) { applyCascadingOperation(entity, CascadeType.PERSIST); }
@Override public void detach(final Object entity) { applyCascadingOperation(entity, CascadeType.DETACH); }