@Override public Query createNamedQuery(final String name) { return createNamedQuery(name, Object.class); }
/** * 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); }
/** * Creates the key that describes the given entity, <b>generating and setting * it if it is presently unset and the given entity type's ID is configured to * be generated on demand</b>. This version of the {@code keyFor()} method * assumes the given object's entity type can be obtained by calling {@code * entity.getClass()}. If you already have a specific entity type in mind, use * the {@link #keyFor(ErraiIdentifiableType, Object)} version of the method. * * @param entityType * The entity type of the entity * @param entity * The entity instance. <b>Side effect: this instance may have its ID * value initialized as a result of this call</b>. * @return The key for the given entity, which--for generated values--may have * just been set on the entity. */ public <X> Key<X, ?> keyFor(final X entity) { final ErraiIdentifiableType<X> entityType = getMetamodel().entity(getNarrowedClass(entity)); return keyFor(entityType, entity); }
@PostConstruct private void setup() { expectedStateEm = new ErraiEntityManager(desiredStateEm, new StorageBackendFactory() { @Override public StorageBackend createInstanceFor(ErraiEntityManager em) { return new WebStorageBackend(em, "expected-state:"); } }); entityComparator = new EntityComparator(desiredStateEm.getMetamodel(), attributeAccessor); }
E resolved = expectedStateEm.find(expectedStateEm.keyFor(requestedNew), Collections.<String,Object>emptyMap()); expectedStateEm.remove(resolved); resolved = desiredStateEm.find(desiredStateEm.keyFor(requestedNew), Collections.<String,Object>emptyMap()); desiredStateEm.remove(resolved); expectedStateEm.merge(actualNew); desiredStateEm.merge(actualNew); DeleteResponse<E> dr = (DeleteResponse<E>) response; System.out.println(" -> Delete " + dr.getEntity()); E resolved = expectedStateEm.find(expectedStateEm.keyFor(dr.getEntity()), Collections.<String,Object>emptyMap()); expectedStateEm.remove(resolved); expectedStateEm.detach(resolved); resolved = desiredStateEm.find(desiredStateEm.keyFor(dr.getEntity()), Collections.<String,Object>emptyMap()); if (resolved != null) { desiredStateEm.remove(resolved); desiredStateEm.detach(resolved); System.out.println(" -> ID Change from " + icr.getOldId() + " to " + icr.getEntity()); E newEntity = icr.getEntity(); newEntity = expectedStateEm.merge(newEntity); ErraiIdentifiableType<E> entityType = desiredStateEm.getMetamodel().entity((Class<E>) newEntity.getClass()); ErraiSingularAttribute<? super E, Object> idAttr = entityType.getId(Object.class); changeId(entityType, icr.getOldId(), idAttr.get(newEntity)); desiredStateEm.merge(newEntity);
final ErraiIdentifiableType<X> entityType = getMetamodel().entity(getNarrowedClass(entity)); final Key<X, ?> key = keyFor(entityType, entity); final EntityState oldState = getState(key, entity); case DETACHED: boolean sendUpdateEvent = true; // if false, send persist event X mergeTarget = find(key, Collections.<String,Object>emptyMap()); if (mergeTarget == null) { sendUpdateEvent = false; cascadeStateChange(attrib, entityToReturn, entity, newState); cascadeStateChange(attrib, entityToReturn, entity, newState);
private static <X, Y> void copySingularAssociation( ErraiEntityManager em, ErraiAttribute<X, Y> attr, X targetEntity, X sourceEntity) { ErraiIdentifiableType<Y> relatedEntityType = em.getMetamodel().entity(attr.getJavaType()); Y oldRelatedEntity = attr.get(sourceEntity); Y resolvedEntity; if (oldRelatedEntity == null) { resolvedEntity = null; } else { Key<Y, ?> key = em.keyFor(oldRelatedEntity); resolvedEntity = em.find(key, Collections.<String,Object>emptyMap()); if (resolvedEntity == null) { resolvedEntity = relatedEntityType.newInstance(); } } attr.set(targetEntity, resolvedEntity); }
protected <C, E> void parsePluralJsonReference( X targetEntity, ErraiPluralAttribute<? super X, C, E> attr, JSONArray attrJsonValues, ErraiEntityManager eem) { if (attrJsonValues == null || attrJsonValues.isNull() != null) return; Class<E> attributeElementType = attr.getElementType().getJavaType(); ErraiIdentifiableType<E> attrEntityType = eem.getMetamodel().entity(attributeElementType); // FIXME this is broken for Map attributes // TODO when we support Map attributes, we should get the attribute with getCollection()/getMap() to fix this warning Collection<E> collection = (Collection<E>) attr.createEmptyCollection(); for (int i = 0; i < attrJsonValues.size(); i++) { Key<E, ?> key = (Key<E, ?>) Key.fromJsonObject(eem, attrJsonValues.get(i).isObject(), true); logger.trace(" looking for " + key); E value = eem.getPartiallyConstructedEntity(key); if (value == null) { value = eem.find(key, Collections.<String,Object>emptyMap()); } collection.add(value); } attr.set(targetEntity, (C) collection); }
/** * 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); }
final TypedQuery<E> query = desiredStateEm.createNamedQuery(queryName, queryResultType); final TypedQuery<E> expectedQuery = expectedStateEm.createNamedQuery(queryName, queryResultType); for (Map.Entry<String, Object> param : queryParams.entrySet()) { query.setParameter(param.getKey(), param.getValue()); expectedResults.put((Key<E, Object>) expectedStateEm.keyFor(expectedState), expectedState); Key<E, ?> key = desiredStateEm.keyFor(desiredState); E expectedState = expectedResults.remove(key); if (expectedState == null) {
@Override public <X> X find(final Class<X> entityClass, final Object primaryKey) { return find(entityClass, primaryKey, Collections.<String, Object>emptyMap()); }
@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; }
final ErraiIdentifiableType<X> entityType = getMetamodel().entity(getNarrowedClass(entity)); if (backend.isModified(key, entity)) { final Object currentId = entityType.getId(Object.class).get(entity);
@Override public void clear() { removedEntities.clear(); final List<?> entities = new ArrayList<>(persistenceContext.values()); for (final Object entity : entities) { detach(entity); } }
@Override public boolean contains(final Object entity) { final Object found = persistenceContext.get(keyFor(entity)); return found == entity; }
final R collectionOfMergeTargets = ((ErraiPluralAttribute<X, R, ?>) cascadeAcross).createEmptyCollection(); for (final Object element : (Iterable<?>) sourceRelatedEntity) { ((Collection) collectionOfMergeTargets).add(applyCascadingOperation(element, cascadeType)); final R resolvedTarget = applyCascadingOperation(sourceRelatedEntity, cascadeType); final Collection<?> children = (Collection<?>) resolvedTargetRelatedEntity; for (final Object child : children) { relatedEntitiesAreManaged &= contains(child); relatedEntitiesAreManaged = contains(resolvedTargetRelatedEntity);
@Override public void persist(final Object entity) { applyCascadingOperation(entity, CascadeType.PERSIST); }
/** * Removes everything from the backend data store and clears the persistence context. */ public void removeAll() { clear(); backend.removeAll(); }
/** * Retrieves the entity instance identified by the given Key. * * @param key The key to look up. Must not be null. * @param properties JPA hints (standard and Errai-specific) for the lookup. * @return the entity instance, or null if the entity cannot be found. */ public <X> X find(final Key<X, ?> key, final Map<String, Object> properties) { X entity = cast(key.getEntityType().getJavaType(), persistenceContext.get(key)); if (entity == null) { entity = backend.get(key); if (entity != null) { persistenceContext.put(key, entity); ((ErraiIdentifiableType<X>) key.getEntityType()).deliverPostLoad(entity); } } return entity; }
private static <X, C, E> void copyPluralAssociation( ErraiEntityManager em, ErraiPluralAttribute<X, C, E> attr, X targetEntity, X sourceEntity) { C oldCollection = attr.get(sourceEntity); C newCollection; if (oldCollection == null) { newCollection = null; } else { newCollection = attr.createEmptyCollection(); ErraiIdentifiableType<E> elemType = em.getMetamodel().entity(attr.getElementType().getJavaType()); // TODO support map-valued plural attributes for (Object oldEntry : (Collection<?>) oldCollection) { Key<Object, ?> key = em.keyFor(oldEntry); Object resolvedEntry = em.find(key, Collections.<String,Object>emptyMap()); if (resolvedEntry == null) { resolvedEntry = elemType.newInstance(); } ((Collection) newCollection).add(resolvedEntry); } } attr.set(targetEntity, newCollection); }