From 4e6b846c342b2c9e9443e3d3472685e5acb32fa3 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Wed, 13 Jul 2016 11:52:51 +0200 Subject: HONEYCOMB-122 Update reader registry to share similar APIs as writer + Extract common registry builder base code (Reader registry is not flat, so there is not full control over ordering as with writers but it is sufficient) + Split CompositeReader into CompositeReader, SubtreeReader and GenericReader + No need to build composite structure in ReaderFactories (registry does that internally) + Keep only ReaderCustomizer + ListReaderCustomizer, no root reader (same for writers) Change-Id: Ic4e5bc96ad47a6cbcada4efcc2209db5c16d2a6c Signed-off-by: Maros Marsalek --- .../impl/read/AbstractCompositeReader.java | 267 --------------------- 1 file changed, 267 deletions(-) delete mode 100644 v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java (limited to 'v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java') diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java deleted file mode 100644 index c99e0edc4..000000000 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * 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 io.fd.honeycomb.v3po.translate.impl.read; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.annotations.Beta; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import io.fd.honeycomb.v3po.translate.impl.TraversalType; -import io.fd.honeycomb.v3po.translate.util.ReflectionUtils; -import io.fd.honeycomb.v3po.translate.util.RWUtils; -import io.fd.honeycomb.v3po.translate.read.ChildReader; -import io.fd.honeycomb.v3po.translate.read.ReadContext; -import io.fd.honeycomb.v3po.translate.read.ReadFailedException; -import io.fd.honeycomb.v3po.translate.read.Reader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.yang.binding.Augmentation; -import org.opendaylight.yangtools.yang.binding.ChildOf; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.Identifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Beta -abstract class AbstractCompositeReader> implements Reader { - - private static final Logger LOG = LoggerFactory.getLogger(AbstractCompositeReader.class); - - private final Map, ChildReader>> childReaders; - private final Map, ChildReader>> augReaders; - private final InstanceIdentifier instanceIdentifier; - private final TraversalType traversalType; - - AbstractCompositeReader(final Class managedDataObjectType, - final List>> childReaders, - final List>> augReaders, - final TraversalType traversalType) { - this.traversalType = traversalType; - this.childReaders = RWUtils.uniqueLinkedIndex(childReaders, RWUtils.MANAGER_CLASS_FUNCTION); - this.augReaders = RWUtils.uniqueLinkedIndex(augReaders, RWUtils.MANAGER_CLASS_AUG_FUNCTION); - this.instanceIdentifier = InstanceIdentifier.create(managedDataObjectType); - } - - @Nonnull - @Override - public final InstanceIdentifier getManagedDataObjectType() { - return instanceIdentifier; - } - - /** - * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present. - * - */ - protected Optional readCurrent(final InstanceIdentifier id, - @Nonnull final ReadContext ctx) throws ReadFailedException { - LOG.debug("{}: Reading current: {}", this, id); - final B builder = getBuilder(id); - // Cache empty value to determine if anything has changed later TODO cache in a field - final D emptyValue = builder.build(); - - switch (traversalType) { - case PREORDER: { - LOG.trace("{}: Reading current attributes", this); - readCurrentAttributes(id, builder, ctx); - readChildren(id, ctx, builder); - break; - } - case POSTORDER: { - readChildren(id, ctx, builder); - LOG.trace("{}: Reading current attributes", this); - readCurrentAttributes(id, builder, ctx); - break; - } - } - - // Need to check whether anything was filled in to determine if data is present or not. - final D built = builder.build(); - final Optional read = built.equals(emptyValue) - ? Optional.absent() - : Optional.of(built); - - LOG.debug("{}: Current node read successfully. Result: {}", this, read); - return read; - } - - private void readChildren(final InstanceIdentifier id, final @Nonnull ReadContext ctx, final B builder) - throws ReadFailedException { - // TODO expect exceptions from reader - for (ChildReader> child : childReaders.values()) { - LOG.debug("{}: Reading child from: {}", this, child); - child.read(id, builder, ctx); - } - - for (ChildReader> child : augReaders.values()) { - LOG.debug("{}: Reading augment from: {}", this, child); - child.read(id, builder, ctx); - } - } - - @Nonnull - @Override - @SuppressWarnings("unchecked") - public Optional read(@Nonnull final InstanceIdentifier id, - @Nonnull final ReadContext ctx) - throws ReadFailedException { - LOG.trace("{}: Reading : {}", this, id); - if (id.getTargetType().equals(getManagedDataObjectType().getTargetType())) { - return readCurrent((InstanceIdentifier) id, ctx); - } else { - return readSubtree(id, ctx); - } - } - - private Optional readSubtree(final InstanceIdentifier id, - @Nonnull final ReadContext ctx) - throws ReadFailedException { - LOG.debug("{}: Reading subtree: {}", this, id); - final Class next = RWUtils.getNextId(id, getManagedDataObjectType()).getType(); - final ChildReader> reader = childReaders.get(next); - final ChildReader> augReader = augReaders.get(next); - - if (reader != null) { - LOG.debug("{}: Reading subtree: {} from: {}", this, id, reader); - return reader.read(id, ctx); - }if (augReader != null) { - LOG.debug("{}: Reading subtree: {} from: {}", this, id, augReader); - return augReader.read(id, ctx); - } else { - LOG.debug("{}: Dedicated subtree reader missing for: {}. Reading current and filtering", this, next); - // If there's no dedicated reader, use read current - final InstanceIdentifier currentId = RWUtils.cutId(id, getManagedDataObjectType()); - final Optional current = readCurrent(currentId, ctx); - // then perform post-reading filtering (return only requested sub-node) - final Optional readSubtree = current.isPresent() - ? filterSubtree(current.get(), id, getManagedDataObjectType().getTargetType()) - : current; - - LOG.debug("{}: Subtree: {} read successfully. Result: {}", this, id, readSubtree); - return readSubtree; - } - } - - /** - * Fill in current node's attributes - * - * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present. - * @param builder Builder object for current node where the read attributes must be placed - * @param ctx Current read context - */ - protected abstract void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final B builder, - @Nonnull final ReadContext ctx) throws ReadFailedException; - - /** - * Return new instance of a builder object for current node - * - * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present. - * @return Builder object for current node type - */ - protected abstract B getBuilder(InstanceIdentifier id); - - // TODO move filtering out of here into a dedicated Filter ifc - @Nonnull - private static Optional filterSubtree(@Nonnull final DataObject parent, - @Nonnull final InstanceIdentifier absolutPath, - @Nonnull final Class managedType) { - final InstanceIdentifier.PathArgument nextId = - RWUtils.getNextId(absolutPath, InstanceIdentifier.create(parent.getClass())); - - final Optional nextParent = findNextParent(parent, nextId, managedType); - - if (Iterables.getLast(absolutPath.getPathArguments()).equals(nextId)) { - return nextParent; // we found the dataObject identified by absolutePath - } else if (nextParent.isPresent()) { - return filterSubtree(nextParent.get(), absolutPath, nextId.getType()); - } else { - return nextParent; // we can't go further, return Optional.absent() - } - } - - private static Optional findNextParent(@Nonnull final DataObject parent, - @Nonnull final InstanceIdentifier.PathArgument nextId, - @Nonnull final Class managedType) { - // TODO is there a better way than reflection ? e.g. convert into NN and filter out with a utility - Optional method = ReflectionUtils.findMethodReflex(managedType, "get", - Collections.>emptyList(), nextId.getType()); - - if (method.isPresent()) { - return Optional.fromNullable(filterSingle(parent, nextId, method.get())); - } else { - // List child nodes - method = ReflectionUtils.findMethodReflex(managedType, - "get" + nextId.getType().getSimpleName(), Collections.>emptyList(), List.class); - - if (method.isPresent()) { - return filterList(parent, nextId, method.get()); - } else { - throw new IllegalStateException( - "Unable to filter " + nextId + " from " + parent + " getters not found using reflexion"); - } - } - } - - @SuppressWarnings("unchecked") - private static Optional filterList(final DataObject parent, - final InstanceIdentifier.PathArgument nextId, - final Method method) { - final List invoke = (List) invoke(method, nextId, parent); - - checkArgument(nextId instanceof InstanceIdentifier.IdentifiableItem, - "Unable to perform wildcarded read for %s", nextId); - final Identifier key = ((InstanceIdentifier.IdentifiableItem) nextId).getKey(); - return Iterables.tryFind(invoke, new Predicate() { - @Override - public boolean apply(@Nullable final DataObject input) { - final Optional keyGetter = - ReflectionUtils.findMethodReflex(nextId.getType(), "get", - Collections.>emptyList(), key.getClass()); - final Object actualKey; - actualKey = invoke(keyGetter.get(), nextId, input); - return key.equals(actualKey); - } - }); - } - - private static DataObject filterSingle(final DataObject parent, - final InstanceIdentifier.PathArgument nextId, final Method method) { - return nextId.getType().cast(invoke(method, nextId, parent)); - } - - private static Object invoke(final Method method, - final InstanceIdentifier.PathArgument nextId, final DataObject parent) { - try { - return method.invoke(parent); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new IllegalArgumentException("Unable to get " + nextId + " from " + parent, e); - } - } - - @Override - public String toString() { - return String.format("Reader[%s]", getManagedDataObjectType().getTargetType().getSimpleName()); - } -} -- cgit 1.2.3-korg