/** * Generates a new ID value for the given entity instance that is guaranteed * to be unique <i>on this client</i>. If the entity instance with this ID is * ever synchronized to the server, this client-local ID will be replaced by a * permanent server-generated ID. * <p> * This method only works for attributes that are configured as * {@code @GeneratedValue}s. The GenerationType has no effect locally, but of * course it will come into play on the server side when and if the entity is * synchronized to the server. * * @param entityInstance * the entity instance to receive the generated ID. This attribute of * that entity instance will be set to the newly generated ID value. * @return the generated ID value, which has already been set on the entity * instance. */ private <X, T> T generateAndSetLocalId(final X entityInstance, final ErraiSingularAttribute<X, T> attr) { final T nextId = attr.getValueGenerator().next(this); attr.set(entityInstance, nextId); return nextId; }
@Override public BigInteger next(ErraiEntityManager entityManager) { BigInteger nextAvailableId = nextCandidateId; while (entityManager.isKeyInUse(new Key<X, BigInteger>((ErraiIdentifiableType<X>) attr.getDeclaringType(), nextAvailableId))) { nextAvailableId = nextAvailableId.add(new BigInteger(String.valueOf(Math.random() * probeJumpSize))); } nextCandidateId = nextAvailableId.add(BigInteger.ONE); return nextAvailableId; }
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); ErraiIdentifiableType<E> entityType = desiredStateEm.getMetamodel().entity(entityClass); ErraiSingularAttribute<? super E, Object> idAttr = entityType.getId(Object.class); ErraiIdGenerator<Object> idGenerator = idAttr.getValueGenerator(); if (idGenerator != null && idGenerator.hasNext(desiredStateEm)) { Object newLocalId = idGenerator.next(desiredStateEm);
Class<Y> attributeType = attr.getJavaType(); Y entityToReference = attr.get(targetEntity); if (entityToReference == null) { return JSONNull.getInstance(); Object idToReference = attrEntityType.getId(Object.class).get(entityToReference); JSONValue ref; if (idToReference == null) {
/** * 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>. * * @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 ErraiIdentifiableType<X> entityType, final X entity) { ErraiSingularAttribute<? super X, ?> idAttr; switch (entityType.getIdType().getPersistenceType()) { case BASIC: idAttr = entityType.getId(entityType.getIdType().getJavaType()); break; default: throw new RuntimeException(entityType.getIdType().getPersistenceType() + " ids are not yet supported"); } Object id = idAttr.get(entity); if ( idAttr.isGeneratedValue() && (id == null || (id instanceof Number && ((Number) id).doubleValue() == 0.0)) ) { id = generateAndSetLocalId(entity, idAttr); // TODO track this generated ID for later reconciliation with the server } return new Key<>(entityType, id); }
protected <Y> void parseSingularJsonReference( X targetEntity, ErraiSingularAttribute<? super X, Y> attr, JSONValue attrJsonValue, ErraiEntityManager eem) { if (attrJsonValue == null || attrJsonValue.isNull() != null) return; Key<Y, ?> key = (Key<Y, ?>) Key.fromJsonObject(eem, attrJsonValue.isObject(), true); logger.trace(" looking for " + key); Y value = eem.find(key, Collections.<String,Object>emptyMap()); attr.set(targetEntity, value); }
final ErraiIdentifiableType<X> entityType = getMetamodel().entity(getNarrowedClass(entity)); if (backend.isModified(key, entity)) { final Object currentId = entityType.getId(Object.class).get(entity); if (!key.getId().equals(currentId)) { throw new PersistenceException(
/** * Returns a Key instance based on the given JSON object. * * @param em * The entity manager that can be used to look up the entity type * corresponding with the key. * @param key * The properties of the key to create. * @param failIfNotFound * If true, and the entity type given in {@code key} is not known to * {@code em}, an IllegalArgumentException will be thrown. * @return An instance of Key that corresponds with the entity type and ID of * the given JSON object. */ public static Key<?, ?> fromJsonObject(ErraiEntityManager em, JSONObject key, boolean failIfNotFound) { String entityClassName = key.get("entityType").isString().stringValue(); ErraiIdentifiableType<Object> et = em.getMetamodel().entity(entityClassName, failIfNotFound); if (et == null) { return null; } ErraiSingularAttribute<?, Object> idAttr = et.getId(Object.class); Object id = JsonUtil.basicValueFromJson(key.get("id"), idAttr.getJavaType()); return new Key<Object, Object>(et, id); } }
/** * 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); }
int index = 0; for (E element : (Iterable<E>) attrValue) { Object idToReference = attrEntityType.getId(Object.class).get(element); JSONValue ref; if (idToReference == null) {
@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 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++; }