@Override public void run(Transaction tx, Key userKey, Contact contact) { Entity user = tx.get(userKey); if (user == null) { System.out.println("Adding a new user."); user = Entity.newBuilder(userKey).set("count", 0L).build(); tx.add(user); } FullEntity<IncompleteKey> contactEntity = FullEntity.newBuilder() .set("email", contact.email()) .set("phone", contact.phone()) .build(); tx.update(Entity.newBuilder(user).set("contact", contactEntity).build()); System.out.printf("Setting contact for user '%s'.%n", userKey.getName()); }
@Override public void run(Transaction tx, Key userKey, String content) { Entity user = tx.get(userKey); if (user == null) { System.out.println("Adding a new user."); user = Entity.newBuilder(userKey).set("count", 1).build(); tx.add(user); } else { user = Entity.newBuilder(user).set("count", user.getLong("count") + 1L).build(); tx.update(user); } IncompleteKey commentKey = IncompleteKey.newBuilder(userKey, COMMENT_KIND).build(); FullEntity<IncompleteKey> comment = FullEntity.newBuilder(commentKey) .set("content", content) .set("timestamp", Timestamp.now()) .build(); tx.addWithDeferredIdAllocation(comment); System.out.printf("Adding a comment to user '%s'.%n", userKey.getName()); }
@Override public Value<FullEntity<?>> saveSafe(final P pojo, final boolean index, final SaveContext ctx, final Path path) throws SkipException { // check if we need to redirect to a different translator if (pojo.getClass() != declaredClass) { // Sometimes generics are more of a hindrance than a help @SuppressWarnings("unchecked") final ClassTranslator<P> translator = (ClassTranslator<P>)byClass.get(pojo.getClass()); if (translator == null) throw new IllegalStateException("Class '" + pojo.getClass() + "' is not a registered @Subclass"); else return translator.save(pojo, index, ctx, path); } else { // This is a normal save final FullEntity.Builder<IncompleteKey> into = FullEntity.newBuilder(); populator.save(pojo, index, ctx, path, into); if (discriminator != null) { into.set(DISCRIMINATOR_PROPERTY, StringValue.newBuilder(discriminator).setExcludeFromIndexes(true).build()); if (!indexedDiscriminators.isEmpty()) into.set(DISCRIMINATOR_INDEX_PROPERTY, ListValue.of(indexedDiscriminators)); } // The question of whether to index this is weird. In order for subthings to be indexed, the entity needs // to be indexed. But then lists with index-heterogeous values (say, nulls) get reordered (!) // by the datastore. So we always index EntityValues and force all the list translators homogenize their lists. // Gross but seems to be the only way. return EntityValue.of(into.build()); } }
EntityValue.Builder valueBuilder = EntityValue.newBuilder(embeddedEntityBuilder.build()); valueBuilder.setExcludeFromIndexes(!embeddedMetadata.isIndexed()); return valueBuilder;
entityBuilder.set(key, toDatastore(entry.getValue()).build()); builder = EntityValue.newBuilder(entityBuilder.build()); } else { throw new MappingException(String.format("Unsupported type: %s", input.getClass().getName()));
return EntityValue.newBuilder(entityBuilder.build()); } catch (Throwable exp) { throw new MappingException(exp);
this.datastoreEntityConverter.write(probe, probeEntityBuilder); FullEntity<IncompleteKey> probeEntity = probeEntityBuilder.build(); DatastorePersistentEntity<?> persistentEntity = this.datastoreMappingContext.getPersistentEntity(example.getProbeType());
@SuppressWarnings("unchecked") @Override public ValueBuilder<?, ?, ?> toDatastore(Object input) { if (input == null) { return NullValue.newBuilder(); } Map<String, ?> map = (Map<String, ?>) input; FullEntity.Builder<IncompleteKey> entityBuilder = FullEntity.newBuilder(); for (Map.Entry<String, ?> entry : map.entrySet()) { String key = entry.getKey(); entityBuilder.set(key, valueMapper.toDatastore(entry.getValue()).build()); } return EntityValue.newBuilder(entityBuilder.build()); }
static FullEntity<?> fromPb(com.google.datastore.v1.Entity entityPb) { return new Builder<>().fill(entityPb).build(); } }
private EntityValue applyEntityValueBuilder(String kindName, Consumer<Builder> consumer) { IncompleteKey key = this.objectToKeyFactory.getIncompleteKey(kindName); FullEntity.Builder<IncompleteKey> builder = FullEntity.newBuilder(key); consumer.accept(builder); return EntityValue.of(builder.build()); }
private EntityValue applyEntityValueBuilder(String kindName, Consumer<Builder> consumer) { IncompleteKey key = this.objectToKeyFactory.getIncompleteKey(kindName); FullEntity.Builder<IncompleteKey> builder = FullEntity.newBuilder(key); consumer.accept(builder); return EntityValue.of(builder.build()); }
@Override public P loadSafe(final Value<FullEntity<?>> container, final LoadContext ctx, final Path path) throws SkipException { // check if we need to redirect to a different translator final String containerDiscriminator = container.get().contains(DISCRIMINATOR_PROPERTY) ? container.get().getString(DISCRIMINATOR_PROPERTY) : null; // wow no Optional or nullable get if (!Objects.equals(discriminator, containerDiscriminator)) { final ClassTranslator<? extends P> translator = byDiscriminator.get(containerDiscriminator); if (translator == null) { throw new IllegalStateException("Datastore object has discriminator value '" + containerDiscriminator + "' but no relevant @Subclass is registered"); } else { // This fixes alsoLoad names in discriminators by changing the discriminator to what the // translator expects for loading that subclass. Otherwise we'll get the error above since the // translator discriminator and the container discriminator won't match. final StringValue discriminatorValue = StringValue.newBuilder(translator.getDiscriminator()).setExcludeFromIndexes(true).build(); final FullEntity<?> updatedEntity = FullEntity.newBuilder(container.get()).set(DISCRIMINATOR_PROPERTY, discriminatorValue).build(); return translator.load(EntityValue.of(updatedEntity), ctx, path); } } else { // This is a normal load if (log.isTraceEnabled()) log.trace(LogUtils.msg(path, "Instantiating a " + declaredClass.getName())); final P into = forge.construct(declaredClass); populator.load(container.get(), ctx, path, into); return into; } }
@Override public Value<FullEntity<?>> save(final Map<Object, Object> pojo, final boolean index, final SaveContext ctx, final Path path) throws SkipException { // Make this work more like collections than atomic values if (pojo == null || pojo.isEmpty()) throw new SkipException(); final FullEntity.Builder<?> emb = FullEntity.newBuilder(); for (final Map.Entry<Object, Object> entry: pojo.entrySet()) { try { final String key = stringifier.toString(entry.getKey()); if (key == null) path.throwNullPointer("null is not allowed as a map key"); final Path propPath = path.extend(key); final Value<?> value = componentTranslator.save(entry.getValue(), index, ctx, propPath); emb.set(key, value); } catch (SkipException e) { // do nothing } } return EntityValue.of(emb.build()); } };
/** * The problem is ProjectionEntity; there's no way to create an EntityValue with a ProjectionEntity * so we can't use the standard translation system for {@code Value<Entity>}. Instead of making the * translation API really complicated, just convert it to a FullEntity. */ private EntityValue makeLoadEntityValue(final BaseEntity<?> ent) { if (ent instanceof FullEntity<?>) { return EntityValue.of((FullEntity<?>)ent); } else { // Sadly there's no more graceful way of doing this final Builder<?> builder = FullEntity.newBuilder(ent.getKey()); for (final String name : ent.getNames()) { final Value<?> value = ent.getValue(name); builder.set(name, value); } return EntityValue.of(builder.build()); } }
/** Example of putting multiple entities with deferred id allocation. */ // [TARGET putWithDeferredIdAllocation(FullEntity...)] public List<Key> multiplePutEntitiesDeferredId() { Datastore datastore = transaction.getDatastore(); // [START multiplePutEntitiesDeferredId] IncompleteKey key1 = datastore.newKeyFactory().setKind("MyKind").newKey(); FullEntity.Builder entityBuilder1 = FullEntity.newBuilder(key1); entityBuilder1.set("propertyName", "value1"); FullEntity entity1 = entityBuilder1.build(); IncompleteKey key2 = datastore.newKeyFactory().setKind("MyKind").newKey(); FullEntity.Builder entityBuilder2 = FullEntity.newBuilder(key2); entityBuilder2.set("propertyName", "value2"); FullEntity entity2 = entityBuilder2.build(); transaction.putWithDeferredIdAllocation(entity1, entity2); Response response = transaction.commit(); // [END multiplePutEntitiesDeferredId] return response.getGeneratedKeys(); }
/** Example of adding multiple entities with deferred id allocation. */ // [TARGET addWithDeferredIdAllocation(FullEntity...)] public List<Key> multipleAddEntitiesDeferredId() { Datastore datastore = transaction.getDatastore(); // [START multipleAddEntitiesDeferredId] IncompleteKey key1 = datastore.newKeyFactory().setKind("MyKind").newKey(); FullEntity.Builder entityBuilder1 = FullEntity.newBuilder(key1); entityBuilder1.set("propertyName", "value1"); FullEntity entity1 = entityBuilder1.build(); IncompleteKey key2 = datastore.newKeyFactory().setKind("MyKind").newKey(); FullEntity.Builder entityBuilder2 = FullEntity.newBuilder(key2); entityBuilder2.set("propertyName", "value2"); FullEntity entity2 = entityBuilder2.build(); transaction.addWithDeferredIdAllocation(entity1, entity2); Response response = transaction.commit(); // [END multipleAddEntitiesDeferredId] return response.getGeneratedKeys(); }
static FullEntity<?> fromPb(com.google.datastore.v1.Entity entityPb) { return new Builder<>().fill(entityPb).build(); } }
@Test public void testCopyFrom() throws Exception { FullEntity.Builder<Key> builder1 = FullEntity.newBuilder(ENTITY); assertEquals(ENTITY, builder1.build()); builder1 = FullEntity.newBuilder(COMPLETE_ENTITY1); assertEquals(COMPLETE_ENTITY1, builder1.build()); FullEntity.Builder<IncompleteKey> builder2 = FullEntity.newBuilder(INCOMPLETE_ENTITY); assertEquals(INCOMPLETE_ENTITY, builder2.build()); } }
@Test public void testNoKey() throws Exception { FullEntity<IncompleteKey> entity = FullEntity.newBuilder().set("foo", "bar").build(); assertFalse(entity.hasKey()); assertNull(entity.getKey()); assertEquals("bar", entity.getString("foo")); entity = FullEntity.newBuilder((IncompleteKey) null).build(); assertFalse(entity.hasKey()); assertNull(entity.getKey()); }