/** * 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, 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; }
/** * 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 <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; }
@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"); } } });
if (idGenerator != null && idGenerator.hasNext(desiredStateEm)) { Object newLocalId = idGenerator.next(desiredStateEm); changeId(entityType, conflictingKey.getId(), newLocalId);