@Override public <X, Y> boolean contains(Key<X, Y> key) { boolean contains = false; for (ErraiManagedType<X> type : key.getEntityType().getSubtypes()) { Key<?, ?> k = new Key<X, Y>(type, key.getId()); String keyJson = namespace + k.toJson(); contains = LocalStorage.get(keyJson) != null; logger.trace("<<<contains '" + keyJson + "' : " + contains); if (contains) break; } return contains; }
private Key<?, ?> parseNamespacedKey(ErraiEntityManager em, String key, boolean failIfNotFound) { if ( (!key.startsWith(namespace)) || namespace.length() >= key.length()) return null; key = key.substring(namespace.length()); if (key.charAt(0) != '{') return null; return Key.fromJson(em, key, failIfNotFound); } }
@Override public <X> X find(final Class<X> entityClass, final Object primaryKey, final Map<String, Object> properties) { final Key<X, ?> key = Key.get(this, entityClass, primaryKey); return find(key, properties); }
/** * Looks up and returns the entity that matches the given key. The key's type * need not be an exact match; any supertype of the requested entity will * suffice. * * @param key * the key to look up. The entity type portion can be any supertype * of the matched entity. The ID is always an exact match. Must not * be null. * @return The entity that matches the ID and has the same type or a subtype * of the type specified in the key. */ @SuppressWarnings("unchecked") public <X> X get(Key<X, ?> key) { for (ErraiManagedType<? extends X> mt : key.getEntityType().getSubtypes()) { Key<? super X, ?> k = new Key<Object, Object>((ErraiManagedType<Object>) mt, key.getId()); X o = (X) contents.get(k); if (o != null) { return o; } } return null; }
@Override public <X> void put(Key<X,?> key, X value) { ErraiManagedType<X> entityType = key.getEntityType(); String keyJson = namespace + key.toJson(); JSONValue valueJson = entityType.toJson(em, value); logger.trace(">>>put '" + keyJson + "'"); LocalStorage.put(keyJson, valueJson.toString()); }
@Override public void visit(String key, String value) { Key<?, ?> k = parseNamespacedKey(em, key, false); if (k == null) return; logger.trace("getAll(): considering " + value); if (type.isSuperclassOf(k.getEntityType())) { logger.trace(" --> correct type"); JSONObject candidate = JSONParser.parseStrict(value).isObject(); Assert.notNull(candidate); if (matcher.matches(candidate)) { @SuppressWarnings("unchecked") Key<X, ?> typedKey = (Key<X, ?>) k; // Unfortunately, this throws away a lot of work we've already done (getting the entity type, // creating the key, doing a backend.get(), parsing the JSON value, ...) // it would be nice to avoid this, but we have to go back to the entity manager in case the // thing we want is in the persistence context. entities.add((X) em.find(k.getEntityType().getJavaType(), typedKey.getId())); } else { logger.trace(" --> but not a match"); } } else { logger.trace(" --> wrong type"); } } });
@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; }
ref = new Key<Y, Object>(attrEntityType, idToReference).toJsonObject();
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); }
@Override public <X> void remove(Key<X, ?> key) { String keyJson = namespace + key.toJson(); LocalStorage.remove(keyJson); }
/** * Returns a JSON string representation of this key which can be turned back * into a Key instance via * {@link Key#fromJson(ErraiEntityManager, String, boolean)}. * * @see #toJsonObject() * @return a JSON-formatted string. Never null. */ public String toJson() { return toJsonObject().toString(); }
/** * 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; }
/** * Tests if this entity manager's storage backend contains an entity that * could conflict with the given key. This method is free of side effects: it * will not affect the contents of the persistence context, and it will not * affect the persistence state of any entity (hence it will not deliver any * events to JPA lifecycle listeners). * * @param key * The key to test for in backend storage. Not null. * @return true if and only if this entity manager's storage backend contains * an entity with the given key. */ public boolean isKeyInUse(final Key<?, ?> key) { // search up the supertype chain for the most generic entity type reachable from the type given in the key ErraiManagedType<?> superManagedType = key.getEntityType(); Class<?> javaType = key.getEntityType().getJavaType().getSuperclass(); while (javaType != null) { final ErraiManagedType<?> mt = metamodel.entity(javaType.getName(), false); if (mt != null) { superManagedType = mt; } javaType = javaType.getSuperclass(); } final Key<?, ?> mostGenericKey = new Key<Object, Object>((ErraiManagedType<Object>) superManagedType, key.getId()); return backend.contains(mostGenericKey); }
@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 <X> boolean isModified(Key<X, ?> key, X value) { ErraiManagedType<X> entityType = key.getEntityType(); String keyJson = namespace + key.toJson(); JSONValue newValueJson = entityType.toJson(em, value); JSONValue oldValueJson = JSONParser.parseStrict(LocalStorage.get(keyJson)); boolean modified = !JsonUtil.equals(newValueJson, oldValueJson); if (modified) { logger.trace("Detected modified entity " + key); logger.trace(" Old: " + oldValueJson); logger.trace(" New: " + newValueJson); } return modified; }
ref = new Key<E, Object>(attrEntityType, idToReference).toJsonObject();
if (idGenerator != null && idGenerator.hasNext(desiredStateEm)) { Object newLocalId = idGenerator.next(desiredStateEm); changeId(entityType, conflictingKey.getId(), newLocalId);
/** * Returns a Key instance based on the given JSON string. * * @param em * The entity manager that can be used to look up the entity type * corresponding with the key. * @param key * The key to parse. * @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 string. */ public static Key<?, ?> fromJson(ErraiEntityManager em, String key, boolean failIfNotFound) { JSONValue k; try { k = JSONParser.parseStrict(key); } catch (JSONException e) { throw new JSONException("Input: " + key, e); } return fromJsonObject(em, k.isObject(), failIfNotFound); }
@Override public <X> X get(Key<X, ?> requestedKey) { for (ErraiManagedType<? extends X> entityType : requestedKey.getEntityType().getSubtypes()) { Key<X, ?> key = new Key<X, Object>((ErraiManagedType<X>) entityType, (Object) requestedKey.getId()); String keyJson = namespace + key.toJson(); String valueJson = LocalStorage.get(keyJson); logger.trace("<<<get '" + keyJson + "' : " + valueJson); X entity; if (valueJson != null) { entity = entityType.fromJson(em, JSONParser.parseStrict(valueJson)); logger.trace(" returning " + entity); return entity; } } return null; }