@Override public InventoryStructure.Offline<?> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { JsonNode tree = jsonParser.readValueAsTree(); if (tree == null) { throw new JsonParseException("Inventory structure expected but got nothing.", jsonParser.getCurrentLocation()); } JsonToken token = tree.asToken(); if (token != JsonToken.START_OBJECT) { throw new JsonParseException("Expected object but got " + token.asString(), JsonLocation.NA); } JsonNode typeNode = tree.get("type"); if (!typeNode.isTextual()) { throw new JsonParseException("'type' must be a text", JsonLocation.NA); } String typeName = typeNode.textValue(); InventoryStructure.EntityType type; try { type = InventoryStructure.EntityType.valueOf(typeName); } catch (IllegalArgumentException e) { throw new JsonParseException("Unrecognized value of 'type'. Supported values are " + LEGAL_ENTITY_TYPES + " but got '" + typeName + "'.", JsonLocation.NA); } Entity.Blueprint root = deserializationContext.readValue( prepareTraverse(tree.get("data"), deserializationContext), type.blueprintType); InventoryStructure.Builder bld = InventoryStructure.Offline.of(root); parseChildren(tree, bld, deserializationContext); return bld.build(); }
private Map.Entry<InventoryStructure<B>, SyncHash.Tree> treeHashAndStructure(Transaction<BE> tx) { BE root = tx.querySingle(context.select().get()); E entity = tx.convert(root, context.entityClass); SyncHash.Tree.Builder bld = SyncHash.Tree.builder(); InventoryStructure.Builder<B> structBld = InventoryStructure.of(Inventory.asBlueprint(entity)); bld.withPath(RelativePath.empty().get()).withHash(entity.getSyncHash()); //the closure is returned in a breadth-first manner Iterator<BE> closure = tx.getTransitiveClosureOver(root, outgoing, contains.name()); if (closure.hasNext()) { Function<BE, Entity<? extends Entity.Blueprint, ?>> convert = e -> (Entity<Entity.Blueprint, ?>) tx.convert(e, tx.extractType(e)); Stream<BE> st = StreamSupport.stream(Spliterators.spliteratorUnknownSize(closure, 0), false); Iterator<Entity<? extends Entity.Blueprint, ?>> entities = st.map(convert).iterator(); buildChildTree(tx, entity.getPath(), singletonList(bld), singletonList(structBld), new ArrayList<>(), new ArrayList<>(), entities.next(), entities); } return new SimpleImmutableEntry<>(structBld.build(), bld.build()); }
public static <R extends Entity.Blueprint> Builder<R> of (R root, Object attachment) { return new Builder<>(root, attachment); }
@Override public Updater<Update, DataEntity> update() { return new Updater<>((u) -> { StructuredData newValue = valueOrDefault(u.getValue(), getValue()); String identityHash = getIdentityHash(); if (u.getValue() != null) { DataEntity.Blueprint updateBlueprint = DataEntity.Blueprint.builder().withRole(getRole()) .withValue(u.getValue()).build(); InventoryStructure<DataEntity.Blueprint> structure = InventoryStructure.of(updateBlueprint).build(); identityHash = IdentityHash.of(structure); } return new DataEntity(this.getPath().up(), this.getRole(), newValue, identityHash, getContentHash(), getSyncHash(), u.getProperties()); }); }
public static <R extends Entity.Blueprint> Builder<R> of (R root, Object attachment) { return new Builder<>(root, attachment); }
private InventoryStructure<B> mergeTree(InventoryStructure<B> currentTree, InventoryStructure<B> newTree, SyncConfiguration configuration) { if (configuration.isDeepSearch()) { return mergeDeepTree(currentTree, RelativePath.empty().get(), InventoryStructure.Offline.copy(newTree).asBuilder(), configuration.getSyncedTypes()).build(); } else { return mergeShallowTree(currentTree, RelativePath.empty().get(), InventoryStructure.Offline.copy(newTree).asBuilder(), configuration.getSyncedTypes()).build(); } }
/** * The entity path is currently only required for resources, which base their content hash on the resource type * path which can be specified using a relative or canonical path in the blueprint. For the content hash to be * consistent we need to convert to just a single representation of the path. * * @param entity the entity to produce the hash of * @param entityPath the canonical path of the entity (can be null for all but resources) * @return the content hash of the entity */ public static String of(Entity.Blueprint entity, CanonicalPath entityPath) { return ComputeHash.of(InventoryStructure.of(entity).build(), entityPath, false, true, false).getContentHash(); } }
/** * You can use this method if you have an existing inventory structure and want to make modifications to it. * * @return a builder seeded with this inventory structure */ public InventoryStructure.Builder<Root> asBuilder() { RelativePath rootPath = EmptyRelativePath.I; Object attachment = getNode(rootPath).getAttachment(); return new InventoryStructure.Builder<>(root, attachment, EmptyRelativePath.I, entities, children); }
/** * You can use this method if you have an existing inventory structure and want to make modifications to it. * * @return a builder seeded with this inventory structure */ public InventoryStructure.Builder<Root> asBuilder() { RelativePath rootPath = EmptyRelativePath.I; Object attachment = getNode(rootPath).getAttachment(); return new InventoryStructure.Builder<>(root, attachment, EmptyRelativePath.I, entities, children); }