/* * Copyright 2015-2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hawkular.inventory.json; import java.io.IOException; import java.io.Serializable; import java.util.function.Supplier; import org.hawkular.inventory.api.model.AbstractHashTree; import org.hawkular.inventory.paths.Path; import org.hawkular.inventory.paths.RelativePath; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; /** * @author Lukas Krejci * @since 0.18.0 */ public class GenericHashTreeDeserializer<T extends AbstractHashTree<T, H>, H extends Serializable> extends JsonDeserializer<T> { private final Supplier<AbstractHashTree.TopBuilder<?, ?, T, H>> topBuilderSupplier; private final Class<H> hashType; public GenericHashTreeDeserializer(Supplier<AbstractHashTree.TopBuilder<?, ?, T, H>> topBuilderSupplier, Class<H> hashType) { this.topBuilderSupplier = topBuilderSupplier; this.hashType = hashType; } @Override public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { AbstractHashTree.TopBuilder<?, ?, T, H> bld = topBuilderSupplier.get(); RelativePath.Extender emptyPath = RelativePath.empty(); deserializeChild(p, bld, emptyPath, ctxt); return bld.build(); } private void deserializeChildren(JsonParser p, AbstractHashTree.Builder<?, ?, T, H> bld, RelativePath.Extender parentPath, DeserializationContext ctx) throws IOException { //make a copy so that we don't modify the parent RelativePath.Extender origParentPath = parentPath; parentPath = origParentPath.get().modified(); RelativePath childPath = null; while (p.nextToken() != null) { switch (p.getCurrentToken()) { case FIELD_NAME: childPath = parentPath.extend(Path.Segment.from(p.getCurrentName())).get(); break; case START_OBJECT: AbstractHashTree.ChildBuilder<?, ?, ?, T, H> childBld = bld.startChild(); deserializeChild(p, childBld, childPath.modified(), ctx); childBld.endChild(); parentPath = origParentPath.get().modified(); break; case END_OBJECT: return; } } } private void deserializeChild(JsonParser p, AbstractHashTree.Builder<?, ?, T, H> bld, RelativePath.Extender childPath, DeserializationContext ctx) throws IOException { bld.withPath(childPath.get()); String currentField = null; while (p.nextToken() != null) { switch (p.getCurrentToken()) { case END_OBJECT: return; case FIELD_NAME: currentField = p.getCurrentName(); break; default: switch (currentField) { case "hash": H hash = ctx.readValue(p, hashType); bld.withHash(hash); break; case "children": deserializeChildren(p, bld, childPath, ctx); break; } } } } }