From: Robert Varga Date: Mon, 21 Jul 2014 13:43:59 +0000 (+0200) Subject: BUG-997: introduce base SchemaRepository X-Git-Tag: release/helium~260^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;ds=sidebyside;h=7df9a3a2afa91112d8fc30430986d03c6a911897;p=yangtools.git BUG-997: introduce base SchemaRepository Change-Id: I51d6c14a217b008afd0fa73c18c6dfc6cc8909b7 Signed-off-by: Robert Varga --- diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java new file mode 100644 index 0000000000..4dd30b90a9 --- /dev/null +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaRepository.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/eplv10.html + */ +package org.opendaylight.yangtools.yang.model.repo.util; + +import com.google.common.base.Optional; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.util.concurrent.AsyncFunction; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceTransformationException; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceTransformer; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaTransformerRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AbstractSchemaRepository implements SchemaRepository, SchemaSourceRegistry { + private static final Logger LOG = LoggerFactory.getLogger(AbstractSchemaRepository.class); + private static final Comparator TRANSFORMER_COST_COMPARATOR = new Comparator() { + @Override + public int compare(final SchemaTransformerRegistration o1, final SchemaTransformerRegistration o2) { + return o1.getInstance().getCost() - o2.getInstance().getCost(); + } + }; + + /* + * Output-type -> transformer map. Our usage involves knowing the destination type, + * so we have to work backwards and find a transformer chain which will get us + * to that representation given our available sources. + */ + private final Multimap, SchemaTransformerRegistration> transformers = + HashMultimap.create(); + + /* + * Source identifier -> representation -> provider map. We usually are looking for + * a specific representation a source. + */ + private final Map, AbstractSchemaSourceRegistration>> sources = new HashMap<>(); + + + private static final ListenableFuture> fetchSource(final SourceIdentifier id, final Iterator it) { + if (!it.hasNext()) { + return Futures.immediateFuture(Optional.absent()); + } + + return Futures.transform(((SchemaSourceProvider)it.next().getProvider()).getSource(id), new AsyncFunction, Optional>() { + @Override + public ListenableFuture> apply(final Optional input) throws Exception { + if (input.isPresent()) { + return Futures.immediateFuture(input); + } else { + return fetchSource(id, it); + } + } + }); + } + + private ListenableFuture> transformSchemaSource(final SourceIdentifier id, final Class representation) { + final Multimap, AbstractSchemaSourceRegistration> srcs = sources.get(id); + if (srcs.isEmpty()) { + return Futures.immediateFailedFuture(new SchemaSourceTransformationException( + String.format("No providers producing a representation of %s registered", id))); + } + + final Collection ts = transformers.get(representation); + if (ts.isEmpty()) { + return Futures.immediateFailedFuture(new SchemaSourceTransformationException( + String.format("No transformers producing representation %s registered", representation))); + } + + // Build up the candidate list + final List candidates = new ArrayList<>(); + for (SchemaTransformerRegistration tr : ts) { + final SchemaSourceTransformer t = tr.getInstance(); + final Class i = t.getInputRepresentation(); + if (srcs.containsKey(i)) { + candidates.add(tr); + } else { + LOG.debug("Provider for {} in {} not found, skipping transfomer {}", id, i, t); + } + } + + if (candidates.isEmpty()) { + return Futures.immediateFailedFuture(new SchemaSourceTransformationException( + String.format("No matching source/transformer pair for source %s representation %s found", id, representation))); + } + + Collections.sort(candidates, TRANSFORMER_COST_COMPARATOR); + // return transform(candidates.iterator(), id); + return null; + } + + /** + * Obtain a SchemaSource is selected representation + */ + protected ListenableFuture> getSchemaSource(final SourceIdentifier id, final Class representation) { + final Multimap, AbstractSchemaSourceRegistration> srcs = sources.get(id); + if (srcs == null) { + LOG.debug("No providers registered for source {}", id); + return Futures.immediateFuture(Optional.absent()); + } + + final Collection candidates = srcs.get(representation); + return Futures.transform(AbstractSchemaRepository.fetchSource(id, candidates.iterator()), new AsyncFunction, Optional>() { + @Override + public ListenableFuture> apply(final Optional input) throws Exception { + if (input.isPresent()) { + return Futures.immediateFuture(input); + } + + return transformSchemaSource(id, representation); + } + }); + } + + @Override + public SchemaContextFactory createSchemaContextFactory(final SchemaSourceFilter filter) { + // TODO Auto-generated method stub + return null; + } + + private void addSource(final SourceIdentifier id, final Class rep, final AbstractSchemaSourceRegistration reg) { + Multimap, AbstractSchemaSourceRegistration> m = sources.get(id); + if (m == null) { + m = HashMultimap.create(); + sources.put(id, m); + } + + m.put(rep, reg); + } + + private void removeSource(final SourceIdentifier id, final Class rep, final SchemaSourceRegistration reg) { + final Multimap, AbstractSchemaSourceRegistration> m = sources.get(id); + if (m != null) { + m.remove(rep, reg); + if (m.isEmpty()) { + sources.remove(m); + } + } + } + + @Override + public SchemaSourceRegistration registerSchemaSource( + final SourceIdentifier identifier, final SchemaSourceProvider provider, final Class representation) { + final AbstractSchemaSourceRegistration ret = new AbstractSchemaSourceRegistration(identifier, provider) { + @Override + protected void removeRegistration() { + removeSource(identifier, representation, this); + } + }; + + addSource(identifier, representation, ret); + return ret; + } + + @Override + public SchemaTransformerRegistration registerSchemaSourceTransformer(final SchemaSourceTransformer transformer) { + final SchemaTransformerRegistration ret = new AbstractSchemaTransformerRegistration(transformer) { + @Override + protected void removeRegistration() { + transformers.remove(transformer.getOutputRepresentation(), this); + } + }; + + transformers.put(transformer.getOutputRepresentation(), ret); + return ret; + } +} diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaSourceRegistration.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaSourceRegistration.java new file mode 100644 index 0000000000..9ed0afefc7 --- /dev/null +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaSourceRegistration.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/eplv10.html + */ +package org.opendaylight.yangtools.yang.model.repo.util; + +import com.google.common.base.Preconditions; + +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration; + +public abstract class AbstractSchemaSourceRegistration extends AbstractObjectRegistration implements SchemaSourceRegistration { + private final SchemaSourceProvider provider; + + protected AbstractSchemaSourceRegistration(final SourceIdentifier identifier, final SchemaSourceProvider provider) { + super(identifier); + this.provider = Preconditions.checkNotNull(provider); + } + + protected SchemaSourceProvider getProvider() { + return provider; + } +} diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaTransformerRegistration.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaTransformerRegistration.java new file mode 100644 index 0000000000..d264ae0545 --- /dev/null +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/repo/util/AbstractSchemaTransformerRegistration.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/eplv10.html + */ +package org.opendaylight.yangtools.yang.model.repo.util; + +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceTransformer; +import org.opendaylight.yangtools.yang.model.repo.spi.SchemaTransformerRegistration; + +public abstract class AbstractSchemaTransformerRegistration extends AbstractObjectRegistration> implements SchemaTransformerRegistration { + protected AbstractSchemaTransformerRegistration( + final SchemaSourceTransformer transformer) { + super(transformer); + } +}