import org.opendaylight.mdsal.binding.api.query.MatchBuilderPath;
import org.opendaylight.mdsal.binding.api.query.QueryExpression;
import org.opendaylight.mdsal.binding.api.query.QueryStructureException;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.ChoiceIn;
import org.opendaylight.yangtools.yang.binding.DataObject;
private final InstanceIdentifierBuilder<T> childPath;
private final QueryBuilderState builder;
- DefaultDescendantQueryBuilder(final BindingCodecTree codec, final InstanceIdentifier<T> rootPath) {
- this.builder = new QueryBuilderState(codec, rootPath);
+ DefaultDescendantQueryBuilder(final DefaultQueryFactory factory, final InstanceIdentifier<T> rootPath) {
+ this.builder = new QueryBuilderState(factory, rootPath);
this.childPath = rootPath.builder();
}
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
+import com.google.common.base.Throwables;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import java.util.ServiceLoader;
+import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
import org.kohsuke.MetaInfServices;
import org.opendaylight.mdsal.binding.api.query.DescendantQueryBuilder;
import org.opendaylight.mdsal.binding.api.query.QueryFactory;
+import org.opendaylight.mdsal.binding.api.query.QueryStructureException;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
+import org.opendaylight.mdsal.binding.dom.codec.spi.BindingSchemaMapping;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@Beta
@MetaInfServices
@Singleton
public final class DefaultQueryFactory implements QueryFactory {
- private final BindingCodecTree codec;
+ private static final class MethodId {
+ final DataNodeContainer parent;
+ final String methodName;
+
+ MethodId(final DataNodeContainer parent, final String methodName) {
+ this.parent = requireNonNull(parent);
+ this.methodName = requireNonNull(methodName);
+ }
+
+ @Override
+ public int hashCode() {
+ return parent.hashCode() * 31 + methodName.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof MethodId)) {
+ return false;
+ }
+ final MethodId other = (MethodId) obj;
+ return methodName.equals(other.methodName) && parent.equals(other.parent);
+ }
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultQueryFactory.class);
+
+ private final LoadingCache<MethodId, NodeIdentifier> knownMethods = CacheBuilder.newBuilder().build(
+ new CacheLoader<MethodId, NodeIdentifier>() {
+ @Override
+ public NodeIdentifier load(final MethodId key) {
+ final DataNodeContainer parent = key.parent;
+ final String methodName = key.methodName;
+
+ for (DataSchemaNode child : parent.getChildNodes()) {
+ if (methodName.equals(BindingSchemaMapping.getGetterMethodName(child))) {
+ return NodeIdentifier.create(child.getQName());
+ }
+ }
+ throw new QueryStructureException("Failed to find schema matching " + methodName + " in " + parent);
+ }
+ });
+ private final @NonNull BindingCodecTree codec;
public DefaultQueryFactory() {
this(ServiceLoader.load(BindingCodecTree.class).findFirst().orElseThrow());
@Override
public <T extends DataObject> DescendantQueryBuilder<T> querySubtree(final InstanceIdentifier<T> rootPath) {
- return new DefaultDescendantQueryBuilder<>(codec, rootPath);
+ return new DefaultDescendantQueryBuilder<>(this, rootPath);
+ }
+
+ @NonNull BindingCodecTree codec() {
+ return codec;
+ }
+
+ @NonNull NodeIdentifier findChild(final DataNodeContainer parent, final String methodName) {
+ try {
+ return knownMethods.get(new MethodId(parent, methodName));
+ } catch (ExecutionException e) {
+ LOG.debug("Failed to find method for {}", methodName, e);
+ final Throwable cause = e.getCause();
+ Throwables.throwIfUnchecked(cause);
+ throw new IllegalStateException("Failed to load cache", e);
+ }
}
}
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.api.query.MatchBuilderPath.LeafReference;
import org.opendaylight.mdsal.binding.api.query.QueryExpression;
-import org.opendaylight.mdsal.binding.api.query.QueryStructureException;
import org.opendaylight.mdsal.binding.dom.adapter.query.LambdaDecoder.LambdaTarget;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
-import org.opendaylight.mdsal.binding.dom.codec.spi.BindingSchemaMapping;
import org.opendaylight.mdsal.dom.api.query.DOMQuery;
import org.opendaylight.mdsal.dom.api.query.DOMQueryPredicate;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
final class QueryBuilderState {
}
}
- private final BindingCodecTree codec;
-
private final List<DOMQueryPredicate> predicates = new ArrayList<>();
+ private final DefaultQueryFactory factory;
private final YangInstanceIdentifier root;
+ private final BindingCodecTree codec;
+
private YangInstanceIdentifier absoluteSelect;
private YangInstanceIdentifier relativeSelect;
- QueryBuilderState(final BindingCodecTree codec, final InstanceIdentifier<?> root) {
- this.codec = requireNonNull(codec);
+ QueryBuilderState(final DefaultQueryFactory factory, final InstanceIdentifier<?> root) {
+ this.codec = factory.codec();
+ this.factory = factory;
this.root = fromBinding(root);
}
final LambdaTarget targetLeaf = LambdaDecoder.resolveLambda(ref);
verify(targetLeaf.targetClass.equals(bindingPath.getTargetType().getName()), "Mismatched target %s and path %s",
targetLeaf, bindingPath);
- final DataSchemaNode child = findChild((DataNodeContainer) targetSchema, targetLeaf.targetMethod);
+ final NodeIdentifier childId = factory.findChild((DataNodeContainer) targetSchema, targetLeaf.targetMethod);
final YangInstanceIdentifier absTarget = fromBinding(bindingPath);
final YangInstanceIdentifier relTarget = absTarget.relativeTo(absoluteSelect)
.orElseThrow(() -> new IllegalStateException(absoluteSelect + " is not an ancestor of " + absTarget));
- return new BoundMethod(relTarget, targetCodec.yangPathArgumentChild(NodeIdentifier.create(child.getQName())));
+ return new BoundMethod(relTarget, targetCodec.yangPathArgumentChild(childId));
}
void addPredicate(final DOMQueryPredicate predicate) {
private @NonNull YangInstanceIdentifier fromBinding(final InstanceIdentifier<?> bindingId) {
return codec.getInstanceIdentifierCodec().fromBinding(bindingId);
}
-
- private static DataSchemaNode findChild(final DataNodeContainer parent, final String methodName) {
- for (DataSchemaNode child : parent.getChildNodes()) {
- if (methodName.equals(BindingSchemaMapping.getGetterMethodName(child))) {
- return child;
- }
- }
- throw new QueryStructureException("Failed to find schema matching " + methodName + " in " + parent);
- }
}