/** * Sets the key (from the container) onto the POJO id/parent fields. Also doublechecks to make sure * that the key fields aren't present in the container, which means we're in a very bad state. */ public void setKey(final P pojo, final FullEntity<?> container, final LoadContext ctx, final Path containerPath) { if (container.contains(idMeta.getProperty().getName())) throw new IllegalStateException("Datastore has a property present for the id field " + idMeta.getProperty() + " which would conflict with the key: " + container); if (parentMeta != null && container.contains(parentMeta.getProperty().getName())) throw new IllegalStateException("Datastore has a property present for the parent field " + parentMeta.getProperty() + " which would conflict with the key: " + container); this.setKey(pojo, container.getKey(), ctx, containerPath); }
/** * Gets the relevant property from the container, detecting alsoload collisions. * * @return the value obtained from the container * @throws IllegalStateException if there are multiple alsoload name matches */ private Value<D> getPropertyFromContainer(final FullEntity<?> container, final Path containerPath) { String foundName = null; Value<D> value = null; for (String name: property.getLoadNames()) { if (container.contains(name)) { if (foundName != null) throw new IllegalStateException("Collision trying to load field; multiple name matches for '" + property.getName() + "' at '" + containerPath.extend(foundName) + "' and '" + containerPath.extend(name) + "'"); //noinspection unchecked value = container.getValue(name); foundName = name; } } if (foundName == null) throw new SkipException(); else return value; }
@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 Object toModel(Value<?> input) { if (input.getType() == ValueType.NULL) { return null; } try { FullEntity<?> entity = ((EntityValue) input).get(); ConstructorMetadata constructorMetadata = metadata.getConstructorMetadata(); Object embeddedObject = constructorMetadata.getConstructorMethodHandle().invoke(); for (PropertyMetadata propertyMetadata : metadata.getPropertyMetadataCollection()) { String mappedName = propertyMetadata.getMappedName(); if (entity.contains(mappedName)) { Value<?> propertyValue = entity.getValue(mappedName); Object fieldValue = propertyMetadata.getMapper().toModel(propertyValue); propertyMetadata.getWriteMethod().invoke(embeddedObject, fieldValue); } } if (constructorMetadata.isBuilderConstructionStrategy()) { embeddedObject = metadata.getConstructorMetadata().getBuildMethodHandle() .invoke(embeddedObject); } return embeddedObject; } catch (Throwable exp) { throw new MappingException(exp); } }