-/**
-
- *
- * March 2013
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
- * Copyright (c) 2013 by Cisco Systems, Inc.
- * 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/epl-v10.html
*/
package org.opendaylight.yangtools.sal.binding.model.api.type.builder;
* The methods as {@link #addAnnotation(String, String)} and
* {@link #setComment(String)} can be used as optional because not all methods
* MUST contain annotation or comment definitions.
- *
- *
+ *
+ *
* @see MethodSignature
*/
public interface MethodSignatureBuilder extends TypeMemberBuilder<MethodSignatureBuilder> {
* the flag <code>isAbstract == true</code> The instantiated Method
* Signature MUST have return value for {@link MethodSignature#isAbstract()}
* also equals to <code>true</code>.
- *
+ *
* @param isAbstract
* is abstract flag
*/
/**
* Adds Parameter into the List of method parameters. Neither the Name or
* Type of parameter can be <code>null</code>.
- *
+ *
* <br>
* In case that any of parameters are defined as <code>null</code> the
* method SHOULD throw an {@link IllegalArgumentException}
- *
+ *
* @param type
* Parameter Type
* @param name
* <code>class</code> or <code>interface</code> definition. In case that
* defining Type will be passed as <code>null</code> reference the method
* SHOULD thrown {@link IllegalArgumentException}.
- *
+ *
* @param definingType
* Defining Type of Method Signature
* @return <code>new</code> <i>immutable</i> instance of Method Signature.
-/**
-
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
- * March 2013
- *
- * Copyright (c) 2013 by Cisco Systems, Inc.
- * 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/epl-v10.html
*/
package org.opendaylight.yangtools.sal.binding.model.api.type.builder;
\ No newline at end of file
-/**
-
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
- * March 2013
- *
- * Copyright (c) 2013 by Cisco Systems, Inc.
- * 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/epl-v10.html
*/
package org.opendaylight.yangtools.sal.binding.model.api.type.provider;
\ No newline at end of file
*/
package org.opendaylight.yangtools.concepts;
-public interface ClassBasedPropertyBuilder<P,T extends ClassBasedPropertyBuilder<P,T>> extends Builder<P> {
-
+public interface ClassBasedPropertyBuilder<P, T extends ClassBasedPropertyBuilder<P, T>> extends Builder<P> {
/**
* Sets a value of property uniquely identified by its
* class.
- *
+ *
* @param type Type of property to set
- * @param value Value of property
+ * @param value Value of property
* @return Builder instance
*/
<V> T set(Class<V> type, V value);
-
+
/**
* Gets a value of property based on its type.
- *
+ *
* @param type Type of property to get
* @return Builder instance
*/
return new CompositeObjectRegistrationBuilder<>(instance);
}
- public static final class CompositeObjectRegistrationBuilder<T> implements //
- Builder<CompositeObjectRegistration<T>> {
+ public static final class CompositeObjectRegistrationBuilder<T> implements Builder<CompositeObjectRegistration<T>> {
private final T instance;
private final Set<Registration> registrations;
*/
package org.opendaylight.yangtools.concepts;
-public interface Deserializer<P,I> {
-
+/**
+ * The concept of a serializer, which produces an object from some input.
+ *
+ * @param <P> Product type
+ * @param <I> Input type
+ */
+public interface Deserializer<P, I> {
+ /**
+ * Produce an object base on input.
+ *
+ * @param input Input object
+ * @return Product derived from input
+ */
P deserialize(I input);
}
*/
package org.opendaylight.yangtools.concepts;
-public interface InvertibleTransformator<P, I> extends Transformator<P, I>{
+public interface InvertibleTransformator<P, I> extends Transformator<P, I> {
I fromProduct(P product);
/**
* Mutable object - object may change it's state during lifecycle.
- *
+ *
* This interface is mutually exclusive with {@link Immutable} and other
* {@link MutationBehaviour}s.
- *
+ *
* @author Tony Tkacik
*
*/
-public interface Mutable extends MutationBehaviour<Mutable>{
-
+public interface Mutable extends MutationBehaviour<Mutable> {
+
}
* @param <P> Product type
*/
public interface ProductAwareBuilder<P> extends Builder<P> {
- /**
- * Return the hash code of the product. This has to be equivalent
- * of calling {@link #build()}.{@link Object#hashCode()}.
- *
- * @return the hash code of the product.
- */
- int productHashCode();
+ /**
+ * Return the hash code of the product. This has to be equivalent
+ * of calling {@link #build()}.{@link Object#hashCode()}.
+ *
+ * @return the hash code of the product.
+ */
+ int productHashCode();
- /**
- * Check whether an instance of the product that would be created
- * by the builder is equal to an existing instance. This has to
- * be equivalent of calling {@link #build()}.{@link Object#equals(Object)}.
- *
- * @param product Product instance
- * @return Return true if the product is equal to the would-be
- * product of the builder.
- */
- boolean productEquals(Object product);
+ /**
+ * Check whether an instance of the product that would be created
+ * by the builder is equal to an existing instance. This has to
+ * be equivalent of calling {@link #build()}.{@link Object#equals(Object)}.
+ *
+ * @param product Product instance
+ * @return Return true if the product is equal to the would-be
+ * product of the builder.
+ */
+ boolean productEquals(Object product);
}
*/
package org.mockito.configuration;
+import java.util.List;
import org.mockito.exceptions.base.MockitoException;
import org.mockito.internal.invocation.InvocationsFinder;
import org.mockito.internal.verification.api.VerificationData;
import org.mockito.invocation.Invocation;
import org.mockito.verification.VerificationMode;
-import java.util.List;
-
/**
* Verifier that extracts arguments from actual invocation. Useful when deeper validation of arguments is needed.
- *
*/
public class ArgumentsExtractorVerifier implements VerificationMode {
- private Object[] arguments;
+ private Object[] arguments;
- @Override
- public void verify(VerificationData data) {
- InvocationsFinder finder = new InvocationsFinder();
- List<Invocation> actualInvocations = finder.findInvocations(data.getAllInvocations(), data.getWanted());
- if (actualInvocations.size() != 1) {
- throw new MockitoException("This verifier can only be used with 1 invocation, got " + actualInvocations.size());
- }
- Invocation invocation = actualInvocations.get(0);
- arguments = invocation.getArguments();
- invocation.markVerified();
+ @Override
+ public void verify(final VerificationData data) {
+ InvocationsFinder finder = new InvocationsFinder();
+ List<Invocation> actualInvocations = finder.findInvocations(data.getAllInvocations(), data.getWanted());
+ if (actualInvocations.size() != 1) {
+ throw new MockitoException("This verifier can only be used with 1 invocation, got " + actualInvocations.size());
+ }
+ Invocation invocation = actualInvocations.get(0);
+ arguments = invocation.getArguments();
+ invocation.markVerified();
- }
- public Object[] getArguments(){
- return arguments;
- }
- }
+ }
+ public Object[] getArguments() {
+ return arguments;
+ }
+}
* Configuration customization for Mockito. Change default answer to {@link ThrowsUnstubbedMethodException}.
*/
public class MockitoConfiguration extends DefaultMockitoConfiguration {
-
- @Override
- public Answer<Object> getDefaultAnswer() {
- return new ThrowsUnstubbedMethodException();
- }
+ @Override
+ public Answer<Object> getDefaultAnswer() {
+ return new ThrowsUnstubbedMethodException();
+ }
}
package org.mockito.configuration;
import java.io.Serializable;
-
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
* Answer that throws {@link UnstubbedMethodException}.
*/
public class ThrowsUnstubbedMethodException implements Answer<Object>, Serializable {
- private static final long serialVersionUID = 1L;
-
- public ThrowsUnstubbedMethodException() {
- }
+ private static final long serialVersionUID = 1L;
@Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Throwable t = new UnstubbedMethodException(invocation.toString() + " was not stubbed");
- throw t;
+ public Object answer(final InvocationOnMock invocation) throws UnstubbedMethodException {
+ throw new UnstubbedMethodException(invocation.toString() + " was not stubbed");
}
}
*/
package org.mockito.configuration;
-
/**
* Exception to be thrown on unstubbed method call.
*/
public class UnstubbedMethodException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
- private static final long serialVersionUID = 1L;
-
- public UnstubbedMethodException(String message) {
- super(message);
- }
-
+ public UnstubbedMethodException(final String message) {
+ super(message);
+ }
}
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.concepts.ProductAwareBuilder;
* a cache in the instantiation path, one can expend some memory on
* indexes and spend some CPU cycles on walking the index to potentially
* end up with a reused object.
- *
+ *
* Note that the cached objects should really be semantically {@link Immutable}.
* This interface does not enforce that interface contract simply because
* there are third-party objects which fulfill this contract.
*/
public interface ObjectCache {
- /**
- * Get a reference for an object which is equal to specified object.
- * The cache is free return either a cached instance, or retain the
- * object and return it back.
- *
- * @param object Requested object, may be null
- * @return Reference to an object which is equal to the one passed in.
- * If @object was @null, this method returns @null.
- */
- <T> T getReference(@Nullable T object);
+ /**
+ * Get a reference for an object which is equal to specified object.
+ * The cache is free return either a cached instance, or retain the
+ * object and return it back.
+ *
+ * @param <T> object type
+ * @param object Requested object, may be null
+ * @return Reference to an object which is equal to the one passed in.
+ * If @object was @null, this method returns @null.
+ */
+ <T> T getReference(@Nullable T object);
- /**
- * Get a reference to an object equal to the product of a builder.
- * The builder is expected to remain constant while this method
- * executes. Unlike {@link #getReference(Object)}, this method has
- * the potential of completely eliding the product instantiation.
- *
- * @param builder Builder instance, may not be null
- * @return Result of builder's toInstance() product, or an equal
- * object.
- */
- <B extends ProductAwareBuilder<P>, P> P getProduct(@Nonnull B builder);
+ /**
+ * Get a reference to an object equal to the product of a builder.
+ * The builder is expected to remain constant while this method
+ * executes. Unlike {@link #getReference(Object)}, this method has
+ * the potential of completely eliding the product instantiation.
+ *
+ * @param <P> produced object type
+ * @param <B> builder type
+ * @param builder Builder instance, may not be null
+ * @return Result of builder's toInstance() product, or an equal
+ * object.
+ */
+ <B extends ProductAwareBuilder<P>, P> P getProduct(@Nonnull B builder);
}
* it at compile-time, but it is not packaged and thus not present at run-time.
*/
public final class StaticObjectCacheBinder extends AbstractObjectCacheBinder {
- private StaticObjectCacheBinder() {
- super(null);
- }
+ private StaticObjectCacheBinder() {
+ super(null);
+ }
- public static StaticObjectCacheBinder getInstance() {
- throw new IllegalStateException("This class should have been replaced");
- }
+ public static StaticObjectCacheBinder getInstance() {
+ throw new IllegalStateException("This class should have been replaced");
+ }
}
protected abstract static class SoftKey<T> extends FinalizableSoftReference<T> {
private final int hashCode;
- public SoftKey(final T referent, final FinalizableReferenceQueue q) {
- super(Preconditions.checkNotNull(referent), q);
+ public SoftKey(final T referent, final FinalizableReferenceQueue queue) {
+ super(Preconditions.checkNotNull(referent), queue);
hashCode = referent.hashCode();
}
*/
package org.opendaylight.yangtools.objcache.spi;
-import javax.annotation.Nonnull;
-
import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
public abstract class AbstractObjectCacheBinder implements ObjectCacheFactoryBinder {
- private final IObjectCacheFactory factory;
+ private final IObjectCacheFactory factory;
- protected AbstractObjectCacheBinder(@Nonnull final IObjectCacheFactory factory) {
- this.factory = Preconditions.checkNotNull(factory);
- }
+ protected AbstractObjectCacheBinder(@Nonnull final IObjectCacheFactory factory) {
+ this.factory = Preconditions.checkNotNull(factory);
+ }
- @Override
- public final IObjectCacheFactory getProductCacheFactory() {
- return factory;
- }
+ @Override
+ public final IObjectCacheFactory getProductCacheFactory() {
+ return factory;
+ }
}
package org.opendaylight.yangtools.objcache.spi;
import javax.annotation.Nonnull;
-
import org.opendaylight.yangtools.objcache.ObjectCache;
public interface IObjectCacheFactory {
- ObjectCache getObjectCache(@Nonnull Class<?> objClass);
+ ObjectCache getObjectCache(@Nonnull Class<?> objClass);
}
* does not do any caching, so it only returns the request object.
*/
public final class NoopObjectCache implements ObjectCache {
- private static final NoopObjectCache INSTANCE = new NoopObjectCache();
+ private static final NoopObjectCache INSTANCE = new NoopObjectCache();
- private NoopObjectCache() {
+ private NoopObjectCache() {
- }
+ }
- /**
- * Get the cache instance. Since the cache does not have any state,
- * this method always returns a singleton instance.
- *
- * @return Cache instance.
- */
- public static NoopObjectCache getInstance() {
- return INSTANCE;
- }
+ /**
+ * Get the cache instance. Since the cache does not have any state,
+ * this method always returns a singleton instance.
+ *
+ * @return Cache instance.
+ */
+ public static NoopObjectCache getInstance() {
+ return INSTANCE;
+ }
- @Override
- public <T> T getReference(final T object) {
- return object;
- }
+ @Override
+ public <T> T getReference(final T object) {
+ return object;
+ }
- @Override
- public <B extends ProductAwareBuilder<P>, P> P getProduct(final B builder) {
- return builder.build();
- }
+ @Override
+ public <B extends ProductAwareBuilder<P>, P> P getProduct(final B builder) {
+ return builder.build();
+ }
}
* Interface binding an implementation into ObjectCacheFactory.
*/
public interface ObjectCacheFactoryBinder {
- /**
- * Get the implementation-specific cache factory.
- *
- * @return Implementation-specific factory.
- */
- IObjectCacheFactory getProductCacheFactory();
+ /**
+ * Get the implementation-specific cache factory.
+ *
+ * @return Implementation-specific factory.
+ */
+ IObjectCacheFactory getProductCacheFactory();
}
*/
package org.opendaylight.yangtools.objcache.guava;
+import com.google.common.base.FinalizableReferenceQueue;
import org.opendaylight.yangtools.objcache.ObjectCache;
import org.opendaylight.yangtools.objcache.spi.IObjectCacheFactory;
-import com.google.common.base.FinalizableReferenceQueue;
-
public final class GuavaObjectCacheFactory implements AutoCloseable, IObjectCacheFactory {
private static final GuavaObjectCacheFactory INSTANCE = new GuavaObjectCacheFactory();
private final FinalizableReferenceQueue queue = new FinalizableReferenceQueue();
@Override
public void close() {
- queue.close();
+ queue.close();
}
+ /**
+ * Return a factory instance.
+ *
+ * @return A factory instance.
+ */
public static GuavaObjectCacheFactory getInstance() {
return INSTANCE;
}
import org.opendaylight.yangtools.objcache.spi.AbstractObjectCacheBinder;
public final class StaticObjectCacheBinder extends AbstractObjectCacheBinder {
- private static final StaticObjectCacheBinder INSTANCE = new StaticObjectCacheBinder();
+ private static final StaticObjectCacheBinder INSTANCE = new StaticObjectCacheBinder();
- private StaticObjectCacheBinder() {
- super(GuavaObjectCacheFactory.getInstance());
- }
+ private StaticObjectCacheBinder() {
+ super(GuavaObjectCacheFactory.getInstance());
+ }
- public static StaticObjectCacheBinder getInstance() {
- return INSTANCE;
- }
+ public static StaticObjectCacheBinder getInstance() {
+ return INSTANCE;
+ }
}
* @param collection Target collection
* @return An unmodifiable view of the collection
*/
- public static <T> Collection<T> create(final @Nonnull Collection<T> collection) {
- if (collection instanceof UnmodifiableCollection || collection instanceof ImmutableCollection ||
- Collections.EMPTY_LIST == collection || Collections.EMPTY_SET == collection ||
- UNMODIFIABLE_COLLECTION_CLASS.isInstance(collection) || SINGLETON_CLASSES.contains(collection.getClass())) {
+ public static <T> Collection<T> create(@Nonnull final Collection<T> collection) {
+ if (collection instanceof UnmodifiableCollection || collection instanceof ImmutableCollection
+ || Collections.EMPTY_LIST == collection || Collections.EMPTY_SET == collection
+ || UNMODIFIABLE_COLLECTION_CLASS.isInstance(collection)
+ || SINGLETON_CLASSES.contains(collection.getClass())) {
return collection;
}
package org.opendaylight.yangtools.util.concurrent;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AbstractListeningExecutorService;
+import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
-
import javax.annotation.Nullable;
-import com.google.common.base.MoreObjects;
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AbstractListeningExecutorService;
-import com.google.common.util.concurrent.ListenableFuture;
-
/**
* An {@link com.google.common.util.concurrent.ListeningExecutorService} implementation that also allows for an {@link Executor} to be
* specified on construction that is used to execute {@link ListenableFuture} callback Runnables,
* @param listenableFutureExecutor the executor used to run listener callbacks asynchronously.
* If null, no executor is used.
*/
- public AsyncNotifyingListeningExecutorService( ExecutorService delegate,
- @Nullable Executor listenableFutureExecutor ) {
+ public AsyncNotifyingListeningExecutorService( final ExecutorService delegate,
+ @Nullable final Executor listenableFutureExecutor ) {
this.delegate = Preconditions.checkNotNull( delegate );
this.listenableFutureExecutor = listenableFutureExecutor;
}
*
* @param task the Callable to execute
*/
- private <T> AsyncNotifyingListenableFutureTask<T> newFutureTask( Callable<T> task ) {
+ private <T> AsyncNotifyingListenableFutureTask<T> newFutureTask( final Callable<T> task ) {
return AsyncNotifyingListenableFutureTask.create( task, listenableFutureExecutor );
}
*
* @param task the Runnable to execute
*/
- private <T> AsyncNotifyingListenableFutureTask<T> newFutureTask( Runnable task, T result ) {
+ private <T> AsyncNotifyingListenableFutureTask<T> newFutureTask( final Runnable task, final T result ) {
return AsyncNotifyingListenableFutureTask.create( task, result, listenableFutureExecutor );
}
}
@Override
- public boolean awaitTermination( long timeout, TimeUnit unit ) throws InterruptedException {
+ public boolean awaitTermination( final long timeout, final TimeUnit unit ) throws InterruptedException {
return delegate.awaitTermination( timeout, unit );
}
}
@Override
- public void execute( Runnable command ) {
+ public void execute( final Runnable command ) {
delegate.execute( command );
}
@Override
- public <T> ListenableFuture<T> submit( Callable<T> task ) {
+ public <T> ListenableFuture<T> submit( final Callable<T> task ) {
AsyncNotifyingListenableFutureTask<T> futureTask = newFutureTask( task );
delegate.execute( futureTask );
return futureTask;
}
@Override
- public ListenableFuture<?> submit( Runnable task ) {
+ public ListenableFuture<?> submit( final Runnable task ) {
AsyncNotifyingListenableFutureTask<Void> futureTask = newFutureTask( task, null );
delegate.execute( futureTask );
return futureTask;
}
@Override
- public <T> ListenableFuture<T> submit( Runnable task, T result ) {
+ public <T> ListenableFuture<T> submit( final Runnable task, final T result ) {
AsyncNotifyingListenableFutureTask<T> futureTask = newFutureTask( task, result );
delegate.execute( futureTask );
return futureTask;
}
- protected ToStringHelper addToStringAttributes( ToStringHelper toStringHelper ) {
+ protected ToStringHelper addToStringAttributes( final ToStringHelper toStringHelper ) {
return toStringHelper;
}
@Override
- public final String toString(){
+ public final String toString() {
return addToStringAttributes( MoreObjects.toStringHelper( this )
.add( "delegate", delegate ) ).toString();
}
*/
package org.opendaylight.yangtools.util.concurrent;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import com.google.common.base.MoreObjects;
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
/**
* A ThreadPoolExecutor with a specified bounded queue capacity that favors reusing previously
* @param threadPrefix
* the name prefix for threads created by this executor.
*/
- public CachedThreadPoolExecutor( int maximumPoolSize, int maximumQueueSize, String threadPrefix ) {
+ public CachedThreadPoolExecutor( final int maximumPoolSize, final int maximumQueueSize, final String threadPrefix ) {
// We're using a custom SynchronousQueue that has a backing bounded LinkedBlockingQueue.
// We don't specify any core threads (first parameter) so, when a task is submitted,
// the base class will always try to offer to the queue. If there is an existing waiting
}
@Override
- public void setRejectedExecutionHandler( RejectedExecutionHandler handler ) {
+ public void setRejectedExecutionHandler( final RejectedExecutionHandler handler ) {
Preconditions.checkNotNull( handler );
rejectedTaskHandler.setDelegateRejectedExecutionHandler( handler );
}
@Override
- public RejectedExecutionHandler getRejectedExecutionHandler(){
+ public RejectedExecutionHandler getRejectedExecutionHandler() {
return rejectedTaskHandler.getDelegateRejectedExecutionHandler();
}
@Override
- public BlockingQueue<Runnable> getQueue(){
+ public BlockingQueue<Runnable> getQueue() {
return executorQueue.getBackingQueue();
}
return ((TrackingLinkedBlockingQueue<?>)executorQueue.getBackingQueue()).getLargestQueueSize();
}
- protected ToStringHelper addToStringAttributes( ToStringHelper toStringHelper ) {
+ protected ToStringHelper addToStringAttributes( final ToStringHelper toStringHelper ) {
return toStringHelper;
}
private final LinkedBlockingQueue<Runnable> backingQueue;
- ExecutorQueue( int maxBackingQueueSize ) {
+ ExecutorQueue( final int maxBackingQueueSize ) {
backingQueue = new TrackingLinkedBlockingQueue<>( maxBackingQueueSize );
}
}
@Override
- public Runnable poll( long timeout, TimeUnit unit ) throws InterruptedException {
+ public Runnable poll( final long timeout, final TimeUnit unit ) throws InterruptedException {
long totalWaitTime = unit.toMillis( timeout );
long waitTime = Math.min( totalWaitTime, POLL_WAIT_TIME_IN_MS );
Runnable task = null;
// periods, one thread will eventually wake up and get the task from the backingQueue
// and execute it, although slightly delayed.
- while( task == null ) {
+ while (task == null) {
// First try to get a task from the backing queue.
task = backingQueue.poll();
- if( task == null ) {
+ if (task == null) {
// No task in backing - call the base class to wait for one to be offered.
task = super.poll( waitTime, TimeUnit.MILLISECONDS );
private final LinkedBlockingQueue<Runnable> backingQueue;
private volatile RejectedExecutionHandler delegateRejectedExecutionHandler;
- RejectedTaskHandler( LinkedBlockingQueue<Runnable> backingQueue,
- RejectedExecutionHandler delegateRejectedExecutionHandler ) {
+ RejectedTaskHandler( final LinkedBlockingQueue<Runnable> backingQueue,
+ final RejectedExecutionHandler delegateRejectedExecutionHandler ) {
this.backingQueue = backingQueue;
this.delegateRejectedExecutionHandler = delegateRejectedExecutionHandler;
}
void setDelegateRejectedExecutionHandler(
- RejectedExecutionHandler delegateRejectedExecutionHandler ) {
+ final RejectedExecutionHandler delegateRejectedExecutionHandler ) {
this.delegateRejectedExecutionHandler = delegateRejectedExecutionHandler;
}
}
@Override
- public void rejectedExecution( Runnable task, ThreadPoolExecutor executor ) {
- if( executor.isShutdown() ) {
+ public void rejectedExecution( final Runnable task, final ThreadPoolExecutor executor ) {
+ if (executor.isShutdown()) {
throw new RejectedExecutionException( "Executor has been shutdown." );
}
- if( !backingQueue.offer( task ) ) {
+ if (!backingQueue.offer(task)) {
delegateRejectedExecutionHandler.rejectedExecution( task, executor );
}
}
package org.opendaylight.yangtools.util.concurrent;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
/**
* A ThreadPoolExecutor with a specified bounded queue capacity that favors creating new threads
* @param threadPrefix
* the name prefix for threads created by this executor.
*/
- public FastThreadPoolExecutor( int maximumPoolSize, int maximumQueueSize, String threadPrefix ) {
+ public FastThreadPoolExecutor( final int maximumPoolSize, final int maximumQueueSize, final String threadPrefix ) {
this( maximumPoolSize, maximumQueueSize, DEFAULT_IDLE_TIMEOUT_IN_SEC, TimeUnit.SECONDS,
threadPrefix );
}
* @param threadPrefix
* the name prefix for threads created by this executor.
*/
- public FastThreadPoolExecutor( int maximumPoolSize, int maximumQueueSize, long keepAliveTime,
- TimeUnit unit, String threadPrefix ) {
+ public FastThreadPoolExecutor( final int maximumPoolSize, final int maximumQueueSize, final long keepAliveTime,
+ final TimeUnit unit, final String threadPrefix ) {
// We use all core threads (the first 2 parameters below equal) so, when a task is submitted,
// if the thread limit hasn't been reached, a new thread will be spawned to execute
// the task even if there is an existing idle thread in the pool. This is faster than
setThreadFactory( new ThreadFactoryBuilder().setDaemon( true )
.setNameFormat( threadPrefix + "-%d" ).build() );
- if( keepAliveTime > 0 ) {
+ if (keepAliveTime > 0) {
// Need to specifically configure core threads to timeout.
allowCoreThreadTimeOut( true );
}
return ((TrackingLinkedBlockingQueue<?>)getQueue()).getLargestQueueSize();
}
- protected ToStringHelper addToStringAttributes( ToStringHelper toStringHelper ) {
+ protected ToStringHelper addToStringAttributes( final ToStringHelper toStringHelper ) {
return toStringHelper;
}
private final String listenerClassName;
private final int currentQueueSize;
- @ConstructorProperties({"listenerClassName","currentQueueSize"})
- public ListenerNotificationQueueStats( String listenerClassName, int currentQueueSize ) {
+ @ConstructorProperties({ "listenerClassName","currentQueueSize" })
+ public ListenerNotificationQueueStats( final String listenerClassName, final int currentQueueSize ) {
this.listenerClassName = listenerClassName;
this.currentQueueSize = currentQueueSize;
}
/**
* Returns the name of the listener class.
*/
- public String getListenerClassName(){
+ public String getListenerClassName() {
return listenerClassName;
}
/**
* Returns the current notification queue size.
*/
- public int getCurrentQueueSize(){
+ public int getCurrentQueueSize() {
return currentQueueSize;
}
}
package org.opendaylight.yangtools.yang.binding;
import static com.google.common.base.Preconditions.checkArgument;
-
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
-
import java.text.SimpleDateFormat;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
public static String getPropertyName(final String yangIdentifier) {
final String potential = toFirstLower(toCamelCase(yangIdentifier));
- if("class".equals(potential)) {
+ if ("class".equals(potential)) {
return "xmlClass";
}
return potential;
*/
package org.opendaylight.yangtools.yang.binding;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
import org.opendaylight.yangtools.util.HashCodeBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
final class InstanceIdentifierBuilderImpl<T extends DataObject> implements InstanceIdentifier.InstanceIdentifierBuilder<T> {
private final ImmutableList.Builder<PathArgument> pathBuilder = ImmutableList.builder();
private final HashCodeBuilder<PathArgument> hashBuilder;
}
@SuppressWarnings("unchecked")
- <N extends DataObject & Identifiable<K> , K extends Identifier<N>> InstanceIdentifierBuilderImpl<N> addNode(final Class<N> listItem, final K listKey) {
+ <N extends DataObject & Identifiable<K>, K extends Identifier<N>> InstanceIdentifierBuilderImpl<N> addNode(final Class<N> listItem, final K listKey) {
arg = new IdentifiableItem<N, K>(listItem, listKey);
hashBuilder.addArgument(arg);
pathBuilder.add(arg);
/*
* @deprecated Use #build() instead.
*/
+ @Override
@Deprecated
public InstanceIdentifier<T> toInstance() {
return build();
+/*
+ * 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/epl-v10.html
+ */
package org.opendaylight.yangtools.yang.binding.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
-
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
* Path, which is nested to parent, and should be readed.
* @return Value of object.
*/
- public static final <T extends DataObject, P extends DataObject> Map<InstanceIdentifier<T>, T> readData(P parent,
- InstanceIdentifier<P> parentPath, InstanceIdentifier<T> childPath) {
+ public static final <T extends DataObject, P extends DataObject> Map<InstanceIdentifier<T>, T> readData(final P parent,
+ final InstanceIdentifier<P> parentPath, final InstanceIdentifier<T> childPath) {
checkArgument(parent != null, "Parent must not be null.");
checkArgument(parentPath != null, "Parent path must not be null");
checkArgument(childPath != null, "Child path must not be null");
}
@SuppressWarnings("rawtypes")
- private static Map<InstanceIdentifier, DataContainer> readData(Entry<InstanceIdentifier, DataContainer> entry,
- PathArgument pathArgument) {
+ private static Map<InstanceIdentifier, DataContainer> readData(final Entry<InstanceIdentifier, DataContainer> entry,
+ final PathArgument pathArgument) {
return readData(entry.getValue(), entry.getKey(), pathArgument);
}
- public static final <T extends DataObject> Optional<T> readData(DataObject source, Class<T> child) {
+ public static final <T extends DataObject> Optional<T> readData(final DataObject source, final Class<T> child) {
checkArgument(source != null, "Object should not be null.");
checkArgument(child != null, "Child type should not be null");
Class<? extends DataContainer> parentClass = source.getImplementedInterface();
}
@SuppressWarnings("rawtypes")
- private static final Map<InstanceIdentifier, DataContainer> readData(DataContainer parent,
- InstanceIdentifier parentPath, PathArgument child) {
+ private static final Map<InstanceIdentifier, DataContainer> readData(final DataContainer parent,
+ final InstanceIdentifier parentPath, final PathArgument child) {
checkArgument(parent != null, "Object should not be null.");
checkArgument(child != null, "Child argument should not be null");
Class<? extends DataContainer> parentClass = parent.getImplementedInterface();
return resolveReadStrategy(parentClass, child.getType()).readUsingPathArgument(parent, child, parentPath);
}
- private static DataObjectReadingStrategy resolveReadStrategy(Class<? extends DataContainer> parentClass,
- Class<? extends DataContainer> type) {
+ private static DataObjectReadingStrategy resolveReadStrategy(final Class<? extends DataContainer> parentClass,
+ final Class<? extends DataContainer> type) {
DataObjectReadingStrategy strategy = createReadStrategy(parentClass, type);
// FIXME: Add caching of strategies
return strategy;
}
- private static DataObjectReadingStrategy createReadStrategy(Class<? extends DataContainer> parent,
- Class<? extends DataContainer> child) {
+ private static DataObjectReadingStrategy createReadStrategy(final Class<? extends DataContainer> parent,
+ final Class<? extends DataContainer> child) {
if (Augmentable.class.isAssignableFrom(parent) && Augmentation.class.isAssignableFrom(child)) {
return REAUSABLE_AUGMENTATION_READING_STRATEGY;
return new ContainerReadingStrategy(parent, child);
}
- private static Method resolveGetterMethod(Class<? extends DataContainer> parent, Class<?> child) {
+ private static Method resolveGetterMethod(final Class<? extends DataContainer> parent, final Class<?> child) {
String methodName = "get" + child.getSimpleName();
try {
return parent.getMethod(methodName);
private final Method getterMethod;
@SuppressWarnings("unchecked")
- public DataObjectReadingStrategy(Class parentType, Class childType) {
+ public DataObjectReadingStrategy(final Class parentType, final Class childType) {
super();
checkArgument(DataContainer.class.isAssignableFrom(parentType));
checkArgument(DataContainer.class.isAssignableFrom(childType));
}
@SuppressWarnings("unchecked")
- public DataObjectReadingStrategy(Class parentType, Class childType, Method getter) {
+ public DataObjectReadingStrategy(final Class parentType, final Class childType, final Method getter) {
this.parentType = parentType;
this.childType = childType;
this.getterMethod = getter;
@SuppressWarnings("rawtypes")
private static class ContainerReadingStrategy extends DataObjectReadingStrategy {
- public ContainerReadingStrategy(Class<? extends DataContainer> parent, Class<? extends DataContainer> child) {
+ public ContainerReadingStrategy(final Class<? extends DataContainer> parent, final Class<? extends DataContainer> child) {
super(parent, child);
checkArgument(child.isAssignableFrom(getGetterMethod().getReturnType()));
}
@Override
- public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(DataContainer parent,
- PathArgument childArgument, InstanceIdentifier parentPath) {
+ public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(final DataContainer parent,
+ final PathArgument childArgument, final InstanceIdentifier parentPath) {
final DataContainer result = read(parent, childArgument.getType());
if (result != null) {
@SuppressWarnings("unchecked")
}
@Override
- public DataContainer read(DataContainer parent, Class<?> childType) {
+ public DataContainer read(final DataContainer parent, final Class<?> childType) {
try {
Object potentialData = getGetterMethod().invoke(parent);
checkState(potentialData instanceof DataContainer);
@SuppressWarnings("rawtypes")
private static class ListItemReadingStrategy extends DataObjectReadingStrategy {
- public ListItemReadingStrategy(Class<? extends DataContainer> parent, Class child) {
+ public ListItemReadingStrategy(final Class<? extends DataContainer> parent, final Class child) {
super(parent, child);
checkArgument(Iterable.class.isAssignableFrom(getGetterMethod().getReturnType()));
}
@Override
- public DataContainer read(DataContainer parent, Class<?> childType) {
+ public DataContainer read(final DataContainer parent, final Class<?> childType) {
// This will always fail since we do not have key.
return null;
}
@SuppressWarnings("unchecked")
@Override
- public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(DataContainer parent,
- PathArgument childArgument, InstanceIdentifier builder) {
+ public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(final DataContainer parent,
+ final PathArgument childArgument, final InstanceIdentifier builder) {
try {
Object potentialList = getGetterMethod().invoke(parent);
if (potentialList instanceof Iterable) {
return Collections.emptyMap();
}
- private Map<InstanceIdentifier, DataContainer> readAll(Iterable<Identifiable> dataList,
- InstanceIdentifier parentPath) {
+ private Map<InstanceIdentifier, DataContainer> readAll(final Iterable<Identifiable> dataList,
+ final InstanceIdentifier parentPath) {
Builder<InstanceIdentifier, DataContainer> result = ImmutableMap
.<InstanceIdentifier, DataContainer> builder();
for (Identifiable item : dataList) {
}
@SuppressWarnings("unchecked")
- private Map<InstanceIdentifier, DataContainer> readUsingIdentifiableItem(Iterable<Identifiable> dataList,
- IdentifiableItem childArgument, InstanceIdentifier parentPath) {
+ private Map<InstanceIdentifier, DataContainer> readUsingIdentifiableItem(final Iterable<Identifiable> dataList,
+ final IdentifiableItem childArgument, final InstanceIdentifier parentPath) {
final Identifier<?> key = childArgument.getKey();
for (Identifiable item : dataList) {
if (key.equals(item.getKey()) && item instanceof DataContainer) {
@SuppressWarnings("rawtypes")
@Override
- public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(DataContainer parent,
- PathArgument childArgument, InstanceIdentifier builder) {
+ public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(final DataContainer parent,
+ final PathArgument childArgument, final InstanceIdentifier builder) {
checkArgument(childArgument instanceof Item<?>, "Path Argument must be Item without keys");
DataContainer aug = read(parent, childArgument.getType());
if (aug != null) {
}
@Override
- public DataContainer read(DataContainer parent, Class<?> childType) {
+ public DataContainer read(final DataContainer parent, final Class<?> childType) {
checkArgument(Augmentation.class.isAssignableFrom(childType), "Parent must be Augmentable.");
checkArgument(parent instanceof Augmentable<?>, "Parent must be Augmentable.");
* @throws IllegalArgumentException
* if parent argument is bigger than child
*/
- private static <P, C> List<C> subList(Iterable<P> parent, Iterable<C> child) {
+ private static <P, C> List<C> subList(final Iterable<P> parent, final Iterable<C> child) {
Iterator<P> iParent = parent.iterator();
List<C> result = new ArrayList<>();
for (C arg : child) {
.build(new CacheLoader<Class<? extends NotificationListener>, NotificationListenerInvoker>() {
@Override
- public NotificationListenerInvoker load(Class<? extends NotificationListener> key) throws Exception {
+ public NotificationListenerInvoker load(final Class<? extends NotificationListener> key) throws Exception {
return createInvoker(key);
}
private final Map<QName, MethodHandle> methodInvokers;
- public NotificationListenerInvoker(Map<QName, MethodHandle> map) {
+ public NotificationListenerInvoker(final Map<QName, MethodHandle> map) {
this.methodInvokers = map;
}
* supplied RPC type.
*
*/
- public static NotificationListenerInvoker from(Class<? extends NotificationListener> type) {
+ public static NotificationListenerInvoker from(final Class<? extends NotificationListener> type) {
Preconditions.checkArgument(type.isInterface());
Preconditions.checkArgument(BindingReflections.isBindingClass(type));
return INVOKERS.getUnchecked(type);
* Input data for RPC.
*
*/
- public void invokeNotification(@Nonnull NotificationListener impl, @Nonnull QName rpcName,
- @Nullable DataContainer input) {
+ public void invokeNotification(@Nonnull final NotificationListener impl, @Nonnull final QName rpcName,
+ @Nullable final DataContainer input) {
Preconditions.checkNotNull(impl, "implemetation must be supplied");
MethodHandle invoker = methodInvokers.get(rpcName);
Preconditions.checkArgument(invoker != null, "Supplied notification is not valid for implementation %s", impl);
}
}
- private static NotificationListenerInvoker createInvoker(Class<? extends NotificationListener> key) {
+ private static NotificationListenerInvoker createInvoker(final Class<? extends NotificationListener> key) {
return new NotificationListenerInvoker(createInvokerMap(key));
}
- private static Map<QName, MethodHandle> createInvokerMap(Class<? extends NotificationListener> key) {
- Builder<QName, MethodHandle> ret = ImmutableMap.<QName, MethodHandle> builder();
+ private static Map<QName, MethodHandle> createInvokerMap(final Class<? extends NotificationListener> key) {
+ Builder<QName, MethodHandle> ret = ImmutableMap.<QName, MethodHandle>builder();
for (Method method : key.getMethods()) {
if (BindingReflections.isNotificationCallback(method)) {
final RpcError... errors) {
super(Preconditions.checkNotNull(message), cause);
- if( errors != null && errors.length > 0 ) {
+ if (errors != null && errors.length > 0) {
errorList = ImmutableList.<RpcError>copyOf( Arrays.asList( errors ) );
- }
- else {
+ } else {
// Add a default RpcError.
errorList = ImmutableList.of(RpcResultBuilder.newError(ErrorType.APPLICATION, null,
getMessage(), null, null, getCause()));
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
-
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
}
@Override
- public String toString(){
+ public String toString() {
return "RpcResult [successful=" + successful + ", result="
+ result + ", errors=" + errors + "]";
}
}
@Override
- public String getMessage(){
+ public String getMessage() {
return message;
}
}
@Override
- public String toString(){
+ public String toString() {
return "RpcError [message=" + message + ", severity="
+ severity + ", errorType=" + errorType + ", tag=" + tag
+ ", applicationTag=" + applicationTag + ", info=" + info
* @param result the result value
*/
public static <T> RpcResultBuilder<T> success( final T result ) {
- return new RpcResultBuilder<T>( true, result );
+ return new RpcResultBuilder<T>( true, result );
}
/**
private void addError( final RpcError error ) {
- if( errors == null ) {
+ if (errors == null) {
errors = new ImmutableList.Builder<RpcError>();
}
* @param errors the list of RpcErrors
*/
public RpcResultBuilder<T> withRpcErrors( final Collection<RpcError> errors ) {
- if( errors != null ) {
- for( RpcError error: errors ) {
+ if (errors != null) {
+ for (RpcError error : errors) {
addError( error );
}
}
import java.io.StringWriter;
import java.util.Map;
import javax.xml.XMLConstants;
-import java.io.StringWriter;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
private final XMLStreamWriter writer;
private final SchemaTracker tracker;
private final XmlStreamUtils streamUtils;
- private RandomPrefix randomPrefix;
+ private final RandomPrefix randomPrefix;
private XMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer, final SchemaContext context, final SchemaPath path) {
this.writer = Preconditions.checkNotNull(writer);
return new XMLStreamNormalizedNodeStreamWriter(writer, context, path);
}
- private void writeStartElement( QName qname) throws XMLStreamException {
+ private void writeStartElement(final QName qname) throws XMLStreamException {
String ns = qname.getNamespace().toString();
writer.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, qname.getLocalName(), ns);
if(writer.getNamespaceContext() != null) {
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base strategy for applying changes to a ContainerNode, irrespective of its
+ * actual type.
+ *
+ * @param <T> Type of the container node
+ */
+abstract class AbstractDataNodeContainerModificationStrategy<T extends DataNodeContainer> extends AbstractNodeContainerModificationStrategy {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractDataNodeContainerModificationStrategy.class);
+ private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
+ .build(new CacheLoader<PathArgument, ModificationApplyOperation>() {
+ @Override
+ public ModificationApplyOperation load(final PathArgument key) throws Exception {
+ if (key instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
+ return SchemaAwareApplyOperation.from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) key);
+ }
+
+ final DataSchemaNode child = schema.getDataChildByName(key.getNodeType());
+ return child == null ? null : SchemaAwareApplyOperation.from(child);
+ }
+ });
+ private final T schema;
+
+ protected AbstractDataNodeContainerModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+ super(nodeClass);
+ this.schema = Preconditions.checkNotNull(schema);
+ }
+
+ protected final T getSchema() {
+ return schema;
+ }
+
+ @Override
+ public final Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ try {
+ return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
+ } catch (ExecutionException e) {
+ LOG.trace("Child {} not present in container schema {}", identifier, this);
+ return Optional.absent();
+ }
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " [" + schema + "]";
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+
+abstract class AbstractNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
+
+ private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+
+ protected AbstractNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+ this.nodeClass = Preconditions.checkNotNull(nodeClass);
+ }
+
+ @Override
+ void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+ for (ModifiedNode childModification : modification.getChildren()) {
+ resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+ checkArgument(nodeClass.isInstance(writtenValue), "Node %s is not of type %s", writtenValue, nodeClass);
+ checkArgument(writtenValue instanceof NormalizedNodeContainer);
+
+ NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
+ for (Object child : container.getValue()) {
+ checkArgument(child instanceof NormalizedNode);
+
+ /*
+ * FIXME: fail-fast semantics:
+ *
+ * We can validate the data structure here, aborting the commit
+ * before it ever progresses to being committed.
+ */
+ }
+ }
+
+ @Override
+ protected TreeNode applyWrite(final ModifiedNode modification,
+ final Optional<TreeNode> currentMeta, final Version version) {
+ final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
+ final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
+
+ if (modification.getChildren().isEmpty()) {
+ return newValueMeta;
+ }
+
+ /*
+ * This is where things get interesting. The user has performed a write and
+ * then she applied some more modifications to it. So we need to make sense
+ * of that an apply the operations on top of the written value. We could have
+ * done it during the write, but this operation is potentially expensive, so
+ * we have left it out of the fast path.
+ *
+ * As it turns out, once we materialize the written data, we can share the
+ * code path with the subtree change. So let's create an unsealed TreeNode
+ * and run the common parts on it -- which end with the node being sealed.
+ *
+ * FIXME: this code needs to be moved out from the prepare() path and into
+ * the read() and seal() paths. Merging of writes needs to be charged
+ * to the code which originated this, not to the code which is
+ * attempting to make it visible.
+ */
+ final MutableTreeNode mutable = newValueMeta.mutable();
+ mutable.setSubtreeVersion(version);
+
+ @SuppressWarnings("rawtypes")
+ final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
+
+ return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
+ }
+
+ /**
+ * Applies write/remove diff operation for each modification child in modification subtree.
+ * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
+ *
+ * @param meta MutableTreeNode (IndexTreeNode)
+ * @param data DataBuilder
+ * @param nodeVersion Version of TreeNode
+ * @param modifications modification operations to apply
+ * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
+ final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
+
+ for (ModifiedNode mod : modifications) {
+ final YangInstanceIdentifier.PathArgument id = mod.getIdentifier();
+ final Optional<TreeNode> cm = meta.getChild(id);
+
+ Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+ if (result.isPresent()) {
+ final TreeNode tn = result.get();
+ meta.addChild(tn);
+ data.addChild(tn.getData());
+ } else {
+ meta.removeChild(id);
+ data.removeChild(id);
+ }
+ }
+
+ meta.setData(data.build());
+ return meta.seal();
+ }
+
+ @Override
+ protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+ final Version version) {
+ // For Node Containers - merge is same as subtree change - we only replace children.
+ return applyTouch(modification, currentMeta, version);
+ }
+
+ @Override
+ public TreeNode applyTouch(final ModifiedNode modification,
+ final TreeNode currentMeta, final Version version) {
+ final MutableTreeNode newMeta = currentMeta.mutable();
+ newMeta.setSubtreeVersion(version);
+
+ /*
+ * The user has issued an empty merge operation. In this case we do not perform
+ * a data tree mutation, do not pass GO, and do not collect useless garbage.
+ */
+ final Collection<ModifiedNode> children = modification.getChildren();
+ if (children.isEmpty()) {
+ modification.resolveModificationType(ModificationType.UNMODIFIED);
+ newMeta.setData(currentMeta.getData());
+ return newMeta.seal();
+ }
+
+ @SuppressWarnings("rawtypes")
+ NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
+
+ /*
+ * TODO: this is not entirely accurate. If there is only an empty merge operation
+ * among the children, its effect is ModificationType.UNMODIFIED. That would
+ * mean this operation can be turned into UNMODIFIED, cascading that further
+ * up the root -- potentially turning the entire transaction into a no-op
+ * from the perspective of physical replication.
+ *
+ * In order to do that, though, we either have to walk the children ourselves
+ * (looking for a non-UNMODIFIED child), or have mutateChildren() pass that
+ * information back to us.
+ */
+ modification.resolveModificationType(ModificationType.SUBTREE_MODIFIED);
+ return mutateChildren(newMeta, dataBuilder, version, children);
+ }
+
+ @Override
+ protected void checkTouchApplicable(final YangInstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataValidationFailedException {
+ if (!modification.getOriginal().isPresent() && !current.isPresent()) {
+ throw new ModifiedNodeDoesNotExistException(path, String.format("Node %s does not exist. Cannot apply modification to its children.", path));
+ }
+
+ SchemaAwareApplyOperation.checkConflicting(path, current.isPresent(), "Node was deleted by other transaction.");
+ checkChildPreconditions(path, modification, current);
+ }
+
+ private void checkChildPreconditions(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
+ final TreeNode currentMeta = current.get();
+ for (NodeModification childMod : modification.getChildren()) {
+ final YangInstanceIdentifier.PathArgument childId = childMod.getIdentifier();
+ final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
+
+ YangInstanceIdentifier childPath = path.node(childId);
+ resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
+ }
+ }
+
+ @Override
+ protected void checkMergeApplicable(final YangInstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataValidationFailedException {
+ if(current.isPresent()) {
+ checkChildPreconditions(path, modification,current);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
+}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
- private final T schema;
+abstract class AbstractValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+ private final T schema;
- protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- super();
+ protected AbstractValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+ this.nodeClass = Preconditions.checkNotNull(nodeClass);
this.schema = schema;
- this.nodeClass = nodeClass;
}
@Override
- protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+ protected final void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
}
@Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ public final Optional<ModificationApplyOperation> getChild(final PathArgument child) {
throw new UnsupportedOperationException("Node " + schema.getPath()
+ "is leaf type node. Child nodes not allowed");
}
@Override
- protected TreeNode applySubtreeChange(final ModifiedNode modification,
+ protected final ChildTrackingPolicy getChildPolicy() {
+ return ChildTrackingPolicy.NONE;
+ }
+
+ @Override
+ protected final TreeNode applyTouch(final ModifiedNode modification,
final TreeNode currentMeta, final Version version) {
throw new UnsupportedOperationException("Node " + schema.getPath()
+ "is leaf type node. Subtree change is not allowed.");
}
@Override
- protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+ protected final TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
// Just overwrite whatever was there
+ modification.resolveModificationType(ModificationType.WRITE);
return applyWrite(modification, null, version);
}
@Override
- protected TreeNode applyWrite(final ModifiedNode modification,
+ protected final TreeNode applyWrite(final ModifiedNode modification,
final Optional<TreeNode> currentMeta, final Version version) {
- return TreeNodeFactory.createTreeNodeRecursively(modification.getWrittenValue(), version);
+ return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
}
@Override
- protected void checkSubtreeModificationApplicable(final YangInstanceIdentifier path, final NodeModification modification,
+ protected final void checkTouchApplicable(final YangInstanceIdentifier path, final NodeModification modification,
final Optional<TreeNode> current) throws IncorrectDataStructureException {
throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
}
-
- public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
- super(schema, (Class) LeafSetEntryNode.class);
- }
- }
-
- public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafModificationStrategy(final LeafSchemaNode schema) {
- super(schema, (Class) LeafNode.class);
- }
- }
}
\ No newline at end of file
*/
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
-
import com.google.common.base.Optional;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
* if it does not have a SchemaContext attached and hence cannot
* perform anything meaningful.
*/
-final class AlwaysFailOperation implements ModificationApplyOperation {
- public static final ModificationApplyOperation INSTANCE = new AlwaysFailOperation();
+final class AlwaysFailOperation extends ModificationApplyOperation {
+ static final ModificationApplyOperation INSTANCE = new AlwaysFailOperation();
private AlwaysFailOperation() {
}
@Override
- public Optional<TreeNode> apply(final ModifiedNode modification,
+ Optional<TreeNode> apply(final ModifiedNode modification,
final Optional<TreeNode> storeMeta, final Version version) {
throw new IllegalStateException("Schema Context is not available.");
}
@Override
- public void checkApplicable(final YangInstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> storeMetadata) {
+ void checkApplicable(final YangInstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> storeMetadata) {
throw new IllegalStateException("Schema Context is not available.");
}
}
@Override
- public void verifyStructure(final ModifiedNode modification) {
+ void verifyStructure(final ModifiedNode modification) {
+ throw new IllegalStateException("Schema Context is not available.");
+ }
+
+ @Override
+ ChildTrackingPolicy getChildPolicy() {
throw new IllegalStateException("Schema Context is not available.");
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import java.util.HashSet;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
+
+final class AugmentationModificationStrategy extends AbstractDataNodeContainerModificationStrategy<AugmentationSchema> {
+ AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
+ super(createAugmentProxy(schema,resolved), AugmentationNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof AugmentationNode);
+ return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
+ }
+
+ private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
+ Set<DataSchemaNode> realChildSchemas = new HashSet<>();
+ for(DataSchemaNode augChild : schema.getChildNodes()) {
+ realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
+ }
+ return new EffectiveAugmentationSchema(schema, realChildSchemas);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+/**
+ * Child ordering policy. It defines how a {@link ModifiedNode} tracks its children.
+ */
+enum ChildTrackingPolicy {
+ /**
+ * No child nodes are possible, ever.
+ */
+ NONE,
+ /**
+ * Child nodes are possible and we need to make sure that their iteration order
+ * matches the order in which they are introduced.
+ */
+ ORDERED,
+ /**
+ * Child nodes are possible, but their iteration order can be undefined.
+ */
+ UNORDERED,
+}
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+final class ChoiceModificationStrategy extends AbstractNodeContainerModificationStrategy {
+ private final Map<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> childNodes;
+
+ ChoiceModificationStrategy(final ChoiceSchemaNode schemaNode) {
+ super(ChoiceNode.class);
+ ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
+
+ for (ChoiceCaseNode caze : schemaNode.getCases()) {
+ for (DataSchemaNode cazeChild : caze.getChildNodes()) {
+ SchemaAwareApplyOperation childNode = SchemaAwareApplyOperation.from(cazeChild);
+ child.put(new YangInstanceIdentifier.NodeIdentifier(cazeChild.getQName()), childNode);
+ }
+ }
+ childNodes = child.build();
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument child) {
+ return Optional.fromNullable(childNodes.get(child));
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof ChoiceNode);
+ return ImmutableChoiceNodeBuilder.create((ChoiceNode) original);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+
+final class ContainerModificationStrategy extends AbstractDataNodeContainerModificationStrategy<ContainerSchemaNode> {
+ ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
+ super(schemaNode, ContainerNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof ContainerNode);
+ return ImmutableContainerNodeBuilder.create((ContainerNode) original);
+ }
+}
\ No newline at end of file
+++ /dev/null
-/*
- * 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/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.data.impl.schema.tree;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
-
-/**
- * Base strategy for applying changes to a ContainerNode, irrespective of its
- * actual type.
- *
- * @param <T> Type of the container node
- */
-abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends NormalizedNodeContainerModificationStrategy {
-
- private final T schema;
- private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
- .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
-
- @Override
- public ModificationApplyOperation apply(final PathArgument identifier) {
- if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
- return SchemaAwareApplyOperation.from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
- }
-
- DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
- if (child == null) {
- return null;
- }
- return SchemaAwareApplyOperation.from(child);
- }
- }));
-
- protected DataNodeContainerModificationStrategy(final T schema,
- final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- super(nodeClass);
- this.schema = schema;
- }
-
- protected T getSchema() {
- return schema;
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- try {
- return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
- } catch (ExecutionException e) {
- return Optional.absent();
- }
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + " [" + schema + "]";
- }
-
- public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy<AugmentationSchema> {
-
- protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
- super(createAugmentProxy(schema,resolved), AugmentationNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof AugmentationNode);
- return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
- }
-
- private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
- Set<DataSchemaNode> realChildSchemas = new HashSet<>();
- for(DataSchemaNode augChild : schema.getChildNodes()) {
- realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
- }
- return new EffectiveAugmentationSchema(schema, realChildSchemas);
- }
- }
-
- public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
-
- public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
- super(schemaNode, ContainerNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof ContainerNode);
- return ImmutableContainerNodeBuilder.create((ContainerNode) original);
- }
- }
-
- public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
-
- protected ListEntryModificationStrategy(final ListSchemaNode schema) {
- super(schema, MapEntryNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof MapEntryNode);
- return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
- }
- }
-
- public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
-
- public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
- super(schemaNode, UnkeyedListEntryNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof UnkeyedListEntryNode);
- return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
- }
- }
-}
\ No newline at end of file
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
@Override
public ModificationType getModificationType() {
- switch (mod.getOperation()) {
- case DELETE:
- return ModificationType.DELETE;
- case MERGE:
- // Merge into non-existing data is a write
- if (oldMeta == null) {
- return ModificationType.WRITE;
- }
-
- // Data-based checks to narrow down types
- final NormalizedNode<?, ?> data = newMeta.getData();
-
- // leaf or anyxml are always written
- if (!(data instanceof NormalizedNodeContainer)) {
- return ModificationType.WRITE;
- }
-
- // Unkeyed collections are always written
- if (data instanceof UnkeyedListNode || data instanceof OrderedMapNode || data instanceof OrderedLeafSetNode) {
- return ModificationType.WRITE;
- }
-
- // Everything else is subtree modified
- return ModificationType.SUBTREE_MODIFIED;
- case TOUCH:
- return ModificationType.SUBTREE_MODIFIED;
- case NONE:
- return ModificationType.UNMODIFIED;
- case WRITE:
- return ModificationType.WRITE;
- }
-
- throw new IllegalStateException("Unhandled internal operation " + mod.getOperation());
+ return mod.modificationType();
}
private Optional<NormalizedNode<?, ?>> optionalData(final TreeNode meta) {
@Override
public DataTreeCandidateNode getModifiedChild(final PathArgument identifier) {
final Optional<ModifiedNode> childMod = mod.getChild(identifier);
- if(childMod.isPresent()) {
+ if (childMod.isPresent()) {
return childNode(mod);
}
return null;
final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
- return new InMemoryDataTree(TreeNodeFactory.createTreeNodeRecursively(data, Version.initial()), null);
+ return new InMemoryDataTree(TreeNodeFactory.createTreeNode(data, Version.initial()), null);
}
/**
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final RootModificationApplyOperation resolver) {
this.snapshot = Preconditions.checkNotNull(snapshot);
this.strategyTree = Preconditions.checkNotNull(resolver).snapshot();
- this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode(), false);
+ this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode(), strategyTree.getChildPolicy());
/*
* We could allocate version beforehand, since Version contract
}
}
- private ModificationApplyOperation resolveModificationStrategy(final YangInstanceIdentifier path) {
- LOG.trace("Resolving modification apply strategy for {}", path);
+ private void upgradeIfPossible() {
if (rootNode.getOperation() == LogicalOperation.NONE) {
strategyTree.upgradeIfPossible();
}
+ }
+
+ private ModificationApplyOperation resolveModificationStrategy(final YangInstanceIdentifier path) {
+ LOG.trace("Resolving modification apply strategy for {}", path);
+ upgradeIfPossible();
return StoreTreeNodes.<ModificationApplyOperation>findNodeChecked(strategyTree, path);
}
private OperationWithModification resolveModificationFor(final YangInstanceIdentifier path) {
- // We ensure strategy is present.
- final ModificationApplyOperation operation = resolveModificationStrategy(path);
-
- final boolean isOrdered;
- if (operation instanceof SchemaAwareApplyOperation) {
- isOrdered = ((SchemaAwareApplyOperation) operation).isOrdered();
- } else {
- isOrdered = true;
- }
+ upgradeIfPossible();
+ /*
+ * Walk the strategy and modification trees in-sync, creating modification nodes as needed.
+ *
+ * If the user has provided wrong input, we may end up with a bunch of TOUCH nodes present
+ * ending with an empty one, as we will throw the exception below. This fact could end up
+ * being a problem, as we'd have bunch of phantom operations.
+ *
+ * That is fine, as we will prune any empty TOUCH nodes in the last phase of the ready
+ * process.
+ */
+ ModificationApplyOperation operation = strategyTree;
ModifiedNode modification = rootNode;
- for (PathArgument pathArg : path.getPathArguments()) {
- modification = modification.modifyChild(pathArg, isOrdered);
+
+ int i = 1;
+ for(PathArgument pathArg : path.getPathArguments()) {
+ Optional<ModificationApplyOperation> potential = operation.getChild(pathArg);
+ if (!potential.isPresent()) {
+ throw new IllegalArgumentException(String.format("Child %s is not present in tree.",
+ Iterables.toString(Iterables.limit(path.getPathArguments(), i))));
+ }
+ operation = potential.get();
+ ++i;
+
+ modification = modification.modifyChild(pathArg, operation.getChildPolicy());
}
+
return OperationWithModification.from(operation, modification);
}
* This class is factory for upgradable root modifications and provides an
* access to set latest backing implementation.
*/
-class LatestOperationHolder {
+final class LatestOperationHolder {
private ModificationApplyOperation current = AlwaysFailOperation.INSTANCE;
*
* @return
*/
- public ModificationApplyOperation getCurrent() {
+ ModificationApplyOperation getCurrent() {
return current;
}
* @param newApplyOper
* New backing implementation
*/
- public void setCurrent(final ModificationApplyOperation newApplyOper) {
+ void setCurrent(final ModificationApplyOperation newApplyOper) {
current = newApplyOper;
}
* @return New upgradable {@link RootModificationApplyOperation} with
* {@link #getCurrent()} used as backing implementation.
*/
- public RootModificationApplyOperation newSnapshot() {
+ RootModificationApplyOperation newSnapshot() {
return new UpgradableModificationApplyOperation(this, current);
}
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+final class LeafModificationStrategy extends AbstractValueNodeModificationStrategy<LeafSchemaNode> {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ LeafModificationStrategy(final LeafSchemaNode schema) {
+ super(schema, (Class) LeafNode.class);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+final class LeafSetEntryModificationStrategy extends AbstractValueNodeModificationStrategy<LeafListSchemaNode> {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
+ super(schema, (Class) LeafSetEntryNode.class);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class ListEntryModificationStrategy extends AbstractDataNodeContainerModificationStrategy<ListSchemaNode> {
+ ListEntryModificationStrategy(final ListSchemaNode schema) {
+ super(schema, MapEntryNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof MapEntryNode);
+ return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
+ }
+}
\ No newline at end of file
import com.google.common.base.Optional;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
/**
- *
* Operation responsible for applying {@link ModifiedNode} on tree.
*
* Operation is composite - operation on top level node consists of
*
* Hierarchical composite operation which is responsible for applying
* modification on particular subtree and creating updated subtree
- *
- *
*/
-interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
-
+abstract class ModificationApplyOperation implements StoreTreeNode<ModificationApplyOperation> {
/**
*
* Implementation of this operation must be stateless and must not change
* node, {@link Optional#absent()} if {@link ModifiedNode}
* resulted in deletion of this node.
*/
- Optional<TreeNode> apply(ModifiedNode modification, Optional<TreeNode> storeMeta, Version version);
+ abstract Optional<TreeNode> apply(ModifiedNode modification, Optional<TreeNode> storeMeta, Version version);
+
+ /**
+ *
+ * Checks if provided node modification could be applied to current metadata node.
+ *
+ * @param modification Modification
+ * @param current Metadata Node to which modification should be applied
+ * @return true if modification is applicable
+ * false if modification is no applicable
+ * @throws DataValidationFailedException
+ */
+ abstract void checkApplicable(YangInstanceIdentifier path, NodeModification modification, Optional<TreeNode> current) throws DataValidationFailedException;
/**
*
* @param modification to be verified.
* @throws IllegalArgumentException If provided NodeModification does not adhere to the structure.
*/
- void verifyStructure(ModifiedNode modification) throws IllegalArgumentException;
+ abstract void verifyStructure(ModifiedNode modification) throws IllegalArgumentException;
/**
- * Returns a suboperation for specified tree node
+ * Return the tracking policy for this node's children.
*
- * @return Reference to suboperation for specified tree node, {@link Optional#absent()}
- * if suboperation is not supported for specified tree node.
+ * @return Tracking policy, may not be null.
*/
- @Override
- Optional<ModificationApplyOperation> getChild(PathArgument child);
+ abstract ChildTrackingPolicy getChildPolicy();
/**
+ * Returns a suboperation for specified tree node
*
- * Checks if provided node modification could be applied to current metadata node.
- *
- * @param modification Modification
- * @param current Metadata Node to which modification should be applied
- * @return true if modification is applicable
- * false if modification is no applicable
- * @throws DataValidationFailedException
+ * @return Reference to suboperation for specified tree node, {@link Optional#absent()}
+ * if suboperation is not supported for specified tree node.
*/
- void checkApplicable(YangInstanceIdentifier path, NodeModification modification, Optional<TreeNode> current) throws DataValidationFailedException;
+ @Override
+ public abstract Optional<ModificationApplyOperation> getChild(PathArgument child);
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
+import com.google.common.base.Verify;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
private LogicalOperation operation = LogicalOperation.NONE;
private Optional<TreeNode> snapshotCache;
private NormalizedNode<?, ?> value;
+ private ModificationType modType;
- private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original, final boolean isOrdered) {
+ private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original, final ChildTrackingPolicy childPolicy) {
this.identifier = identifier;
this.original = original;
- if (isOrdered) {
+ switch (childPolicy) {
+ case NONE:
+ children = Collections.emptyMap();
+ break;
+ case ORDERED:
children = new LinkedHashMap<>();
- } else {
+ break;
+ case UNORDERED:
children = new HashMap<>();
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported child tracking policy " + childPolicy);
}
}
return original;
}
-
@Override
LogicalOperation getOperation() {
return operation;
* If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED}
* changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
*
- * @param child
+ * @param child child identifier, may not be null
+ * @param childPolicy child tracking policy for the node we are looking for
* @return {@link ModifiedNode} for specified child, with {@link #getOriginal()}
* containing child metadata if child was present in original data.
*/
- ModifiedNode modifyChild(final PathArgument child, final boolean isOrdered) {
+ ModifiedNode modifyChild(@Nonnull final PathArgument child, @Nonnull final ChildTrackingPolicy childPolicy) {
clearSnapshot();
if (operation == LogicalOperation.NONE) {
- updateModificationType(LogicalOperation.TOUCH);
+ updateOperationType(LogicalOperation.TOUCH);
}
final ModifiedNode potential = children.get(child);
if (potential != null) {
currentMetadata = Optional.absent();
}
- final ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata, isOrdered);
+ final ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata, childPolicy);
children.put(child, newlyCreated);
return newlyCreated;
}
clearSnapshot();
children.clear();
this.value = null;
- updateModificationType(newType);
+ updateOperationType(newType);
}
/**
*/
void write(final NormalizedNode<?, ?> value) {
clearSnapshot();
- updateModificationType(LogicalOperation.WRITE);
+ updateOperationType(LogicalOperation.WRITE);
children.clear();
this.value = value;
}
void merge(final NormalizedNode<?, ?> value) {
clearSnapshot();
- updateModificationType(LogicalOperation.MERGE);
+ updateOperationType(LogicalOperation.MERGE);
/*
* Blind overwrite of any previous data is okay, no matter whether the node
// A TOUCH node without any children is a no-op
if (operation == LogicalOperation.TOUCH && children.isEmpty()) {
- updateModificationType(LogicalOperation.NONE);
+ updateOperationType(LogicalOperation.NONE);
}
}
return snapshot;
}
- private void updateModificationType(final LogicalOperation type) {
+ private void updateOperationType(final LogicalOperation type) {
operation = type;
+ modType = null;
clearSnapshot();
}
+ operation + ", childModification=" + children + "]";
}
+ void resolveModificationType(@Nonnull final ModificationType type) {
+ modType = type;
+ }
+
+ @Nonnull ModificationType modificationType() {
+ return Verify.verifyNotNull(modType, "Node %s does not have resolved modification type", this);
+ }
+
/**
* Create a node which will reflect the state of this node, except it will behave as newly-written
* value. This is useful only for merge validation.
* @return An isolated node. This node should never reach a datatree.
*/
ModifiedNode asNewlyWritten(final NormalizedNode<?, ?> value) {
- final ModifiedNode ret = new ModifiedNode(getIdentifier(), Optional.<TreeNode>absent(), false);
+ /*
+ * We are instantiating an "equivalent" of this node. Currently the only callsite does not care
+ * about the actual iteration order, so we do not have to specify the same tracking policy as
+ * we were instantiated with. Since this is the only time we need to know that policy (it affects
+ * only things in constructor), we do not want to retain it (saves some memory on per-instance
+ * basis).
+ *
+ * We could reconstruct it using two instanceof checks (to undo what the constructor has done),
+ * which would give perfect results. The memory saving would be at most 32 bytes of a short-lived
+ * object, so let's not bother with that.
+ */
+ final ModifiedNode ret = new ModifiedNode(getIdentifier(), Optional.<TreeNode>absent(), ChildTrackingPolicy.UNORDERED);
ret.write(value);
return ret;
}
- public static ModifiedNode createUnmodified(final TreeNode metadataTree, final boolean isOrdered) {
- return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), isOrdered);
+ public static ModifiedNode createUnmodified(final TreeNode metadataTree, final ChildTrackingPolicy childPolicy) {
+ return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), childPolicy);
}
}
+++ /dev/null
-/*
- * 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/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.data.impl.schema.tree;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableMap;
-import java.util.Collection;
-import java.util.Map;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
-
- private final Class<? extends NormalizedNode<?, ?>> nodeClass;
-
- protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- this.nodeClass = nodeClass;
- }
-
- @Override
- public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
- for (ModifiedNode childModification : modification.getChildren()) {
- resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
- }
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
- checkArgument(nodeClass.isInstance(writtenValue), "Node %s is not of type %s", writtenValue, nodeClass);
- checkArgument(writtenValue instanceof NormalizedNodeContainer);
-
- NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
- for (Object child : container.getValue()) {
- checkArgument(child instanceof NormalizedNode);
-
- /*
- * FIXME: fail-fast semantics:
- *
- * We can validate the data structure here, aborting the commit
- * before it ever progresses to being committed.
- */
- }
- }
-
- @Override
- protected TreeNode applyWrite(final ModifiedNode modification,
- final Optional<TreeNode> currentMeta, final Version version) {
- final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
- final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
-
- if (modification.getChildren().isEmpty()) {
- return newValueMeta;
- }
-
- /*
- * This is where things get interesting. The user has performed a write and
- * then she applied some more modifications to it. So we need to make sense
- * of that an apply the operations on top of the written value. We could have
- * done it during the write, but this operation is potentially expensive, so
- * we have left it out of the fast path.
- *
- * As it turns out, once we materialize the written data, we can share the
- * code path with the subtree change. So let's create an unsealed TreeNode
- * and run the common parts on it -- which end with the node being sealed.
- *
- * FIXME: this code needs to be moved out from the prepare() path and into
- * the read() and seal() paths. Merging of writes needs to be charged
- * to the code which originated this, not to the code which is
- * attempting to make it visible.
- */
- final MutableTreeNode mutable = newValueMeta.mutable();
- mutable.setSubtreeVersion(version);
-
- @SuppressWarnings("rawtypes")
- final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
-
- return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
- }
-
- /**
- * Applies write/remove diff operation for each modification child in modification subtree.
- * Operation also sets the Data tree references for each Tree Node (Index Node) in meta (MutableTreeNode) structure.
- *
- * @param meta MutableTreeNode (IndexTreeNode)
- * @param data DataBuilder
- * @param nodeVersion Version of TreeNode
- * @param modifications modification operations to apply
- * @return Sealed immutable copy of TreeNode structure with all Data Node references set.
- */
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
- final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
-
- for (ModifiedNode mod : modifications) {
- final YangInstanceIdentifier.PathArgument id = mod.getIdentifier();
- final Optional<TreeNode> cm = meta.getChild(id);
-
- Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
- if (result.isPresent()) {
- final TreeNode tn = result.get();
- meta.addChild(tn);
- data.addChild(tn.getData());
- } else {
- meta.removeChild(id);
- data.removeChild(id);
- }
- }
-
- meta.setData(data.build());
- return meta.seal();
- }
-
- @Override
- protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
- final Version version) {
- // For Node Containers - merge is same as subtree change - we only replace children.
- return applySubtreeChange(modification, currentMeta, version);
- }
-
- @Override
- public TreeNode applySubtreeChange(final ModifiedNode modification,
- final TreeNode currentMeta, final Version version) {
- final MutableTreeNode newMeta = currentMeta.mutable();
- newMeta.setSubtreeVersion(version);
-
- /*
- * The user has issued an empty merge operation. In this case we do not perform
- * a data tree mutation, do not pass GO, and do not collect useless garbage.
- */
- final Collection<ModifiedNode> children = modification.getChildren();
- if (children.isEmpty()) {
- newMeta.setData(currentMeta.getData());
- return newMeta.seal();
- }
-
- @SuppressWarnings("rawtypes")
- NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
-
- return mutateChildren(newMeta, dataBuilder, version, children);
- }
-
- @Override
- protected void checkSubtreeModificationApplicable(final YangInstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- if (!modification.getOriginal().isPresent() && !current.isPresent()) {
- throw new ModifiedNodeDoesNotExistException(path, String.format("Node %s does not exist. Cannot apply modification to its children.", path));
- }
-
- SchemaAwareApplyOperation.checkConflicting(path, current.isPresent(), "Node was deleted by other transaction.");
- checkChildPreconditions(path, modification, current);
- }
-
- private void checkChildPreconditions(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
- final TreeNode currentMeta = current.get();
- for (NodeModification childMod : modification.getChildren()) {
- final YangInstanceIdentifier.PathArgument childId = childMod.getIdentifier();
- final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
-
- YangInstanceIdentifier childPath = path.node(childId);
- resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
- }
- }
-
- @Override
- protected void checkMergeApplicable(final YangInstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- if(current.isPresent()) {
- checkChildPreconditions(path, modification,current);
- }
- }
-
- @SuppressWarnings("rawtypes")
- protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
-
- public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Map<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> childNodes;
-
- public ChoiceModificationStrategy(final ChoiceSchemaNode schemaNode) {
- super(ChoiceNode.class);
- ImmutableMap.Builder<YangInstanceIdentifier.PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
-
- for (ChoiceCaseNode caze : schemaNode.getCases()) {
- for (DataSchemaNode cazeChild : caze.getChildNodes()) {
- SchemaAwareApplyOperation childNode = SchemaAwareApplyOperation.from(cazeChild);
- child.put(new YangInstanceIdentifier.NodeIdentifier(cazeChild.getQName()), childNode);
- }
- }
- childNodes = child.build();
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument child) {
- return Optional.fromNullable(childNodes.get(child));
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof ChoiceNode);
- return ImmutableChoiceNodeBuilder.create((ChoiceNode) original);
- }
- }
-
- public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
- super((Class) LeafSetNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new ValueNodeModificationStrategy.LeafSetEntryModificationStrategy(schema));
- }
-
- @Override
- boolean isOrdered() {
- return true;
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof OrderedLeafSetNode<?>);
- return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
- if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
- return entryStrategy;
- }
- return Optional.absent();
- }
- }
-
- public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
- super(OrderedMapNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.ListEntryModificationStrategy(schema));
- }
-
- @Override
- boolean isOrdered() {
- return true;
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof OrderedMapNode);
- return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
- if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- public String toString() {
- return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
- }
- }
-
- public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
- super((Class) LeafSetNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new ValueNodeModificationStrategy.LeafSetEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof LeafSetNode<?>);
- return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
- if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
- return entryStrategy;
- }
- return Optional.absent();
- }
- }
-
- public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
- super(MapNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.ListEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof MapNode);
- return ImmutableMapNodeBuilder.create((MapNode) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
- if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- public String toString() {
- return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
- }
- }
-}
private OperationWithModification forChild(final PathArgument childId) {
ModificationApplyOperation childOp = applyOperation.getChild(childId).get();
-
- final boolean isOrdered;
- if (childOp instanceof SchemaAwareApplyOperation) {
- isOrdered = ((SchemaAwareApplyOperation) childOp).isOrdered();
- } else {
- isOrdered = true;
- }
-
- ModifiedNode childMod = modification.modifyChild(childId, isOrdered);
+ ModifiedNode childMod = modification.modifyChild(childId, childOp.getChildPolicy());
return from(childOp,childMod);
}
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Optional;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+final class OrderedLeafSetModificationStrategy extends AbstractNodeContainerModificationStrategy {
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ super((Class) LeafSetNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+ }
+
+ @Override
+ protected ChildTrackingPolicy getChildPolicy() {
+ return ChildTrackingPolicy.ORDERED;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof OrderedLeafSetNode<?>);
+ return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Optional;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class OrderedMapModificationStrategy extends AbstractNodeContainerModificationStrategy {
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ OrderedMapModificationStrategy(final ListSchemaNode schema) {
+ super(OrderedMapNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
+ }
+
+ @Override
+ protected ChildTrackingPolicy getChildPolicy() {
+ return ChildTrackingPolicy.ORDERED;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof OrderedMapNode);
+ return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public String toString() {
+ return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
+ }
+}
\ No newline at end of file
package org.opendaylight.yangtools.yang.data.impl.schema.tree;
import com.google.common.base.Optional;
-
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
* update user did not invoked any operation.
*
*/
-abstract class RootModificationApplyOperation implements ModificationApplyOperation {
+abstract class RootModificationApplyOperation extends ModificationApplyOperation {
@Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ public final Optional<ModificationApplyOperation> getChild(final PathArgument child) {
return getDelegate().getChild(child);
}
@Override
- public final void checkApplicable(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current)
+ final void checkApplicable(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current)
throws DataValidationFailedException {
getDelegate().checkApplicable(path, modification, current);
}
@Override
- public final Optional<TreeNode> apply(final ModifiedNode modification, final Optional<TreeNode> currentMeta,
+ final Optional<TreeNode> apply(final ModifiedNode modification, final Optional<TreeNode> currentMeta,
final Version version) {
return getDelegate().apply(modification, currentMeta, version);
}
@Override
- public boolean equals(final Object obj) {
+ public final boolean equals(final Object obj) {
return getDelegate().equals(obj);
}
@Override
- public int hashCode() {
+ public final int hashCode() {
return getDelegate().hashCode();
}
@Override
- public String toString() {
+ public final String toString() {
return getDelegate().toString();
}
@Override
- public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+ final void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
getDelegate().verifyStructure(modification);
}
+ @Override
+ final ChildTrackingPolicy getChildPolicy() {
+ return getDelegate().getChildPolicy();
+ }
+
/**
* Return the underlying delegate.
*
* @return Derived {@link RootModificationApplyOperation} with separate
* upgrade lifecycle.
*/
- public abstract RootModificationApplyOperation snapshot();
+ abstract RootModificationApplyOperation snapshot();
/**
* Upgrades backing implementation to latest available, if possible.
* operation and latest operation is updated by
* {@link LatestOperationHolder#setCurrent(ModificationApplyOperation)}.
*/
- public abstract void upgradeIfPossible();
+ abstract void upgradeIfPossible();
- public static RootModificationApplyOperation from(final ModificationApplyOperation resolver) {
+ static RootModificationApplyOperation from(final ModificationApplyOperation resolver) {
if (resolver instanceof RootModificationApplyOperation) {
return ((RootModificationApplyOperation) resolver).snapshot();
}
import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.Version;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
+abstract class SchemaAwareApplyOperation extends ModificationApplyOperation {
private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class);
public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
if (schemaNode instanceof ContainerSchemaNode) {
- return new DataNodeContainerModificationStrategy.ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
+ return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
} else if (schemaNode instanceof ListSchemaNode) {
return fromListSchemaNode((ListSchemaNode) schemaNode);
} else if (schemaNode instanceof ChoiceSchemaNode) {
- return new NormalizedNodeContainerModificationStrategy.ChoiceModificationStrategy((ChoiceSchemaNode) schemaNode);
+ return new ChoiceModificationStrategy((ChoiceSchemaNode) schemaNode);
} else if (schemaNode instanceof LeafListSchemaNode) {
return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
} else if (schemaNode instanceof LeafSchemaNode) {
- return new ValueNodeModificationStrategy.LeafModificationStrategy((LeafSchemaNode) schemaNode);
+ return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
}
throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
}
for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
for (DataSchemaNode child : potential.getChildNodes()) {
if (identifier.getPossibleChildNames().contains(child.getQName())) {
- return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(potential, resolvedTree);
+ return new AugmentationModificationStrategy(potential, resolvedTree);
}
}
}
return new UnkeyedListModificationStrategy(schemaNode);
}
if (schemaNode.isUserOrdered()) {
- return new NormalizedNodeContainerModificationStrategy.OrderedMapModificationStrategy(schemaNode);
+ return new OrderedMapModificationStrategy(schemaNode);
}
- return new NormalizedNodeContainerModificationStrategy.UnorderedMapModificationStrategy(schemaNode);
+ return new UnorderedMapModificationStrategy(schemaNode);
}
private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
if(schemaNode.isUserOrdered()) {
- return new NormalizedNodeContainerModificationStrategy.OrderedLeafSetModificationStrategy(schemaNode);
+ return new OrderedLeafSetModificationStrategy(schemaNode);
} else {
- return new NormalizedNodeContainerModificationStrategy.UnorderedLeafSetModificationStrategy(schemaNode);
+ return new UnorderedLeafSetModificationStrategy(schemaNode);
}
}
}
@Override
- public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+ void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
if (modification.getOperation() == LogicalOperation.WRITE) {
verifyWrittenStructure(modification.getWrittenValue());
}
}
@Override
- public final void checkApplicable(final YangInstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
+ final void checkApplicable(final YangInstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
switch (modification.getOperation()) {
case DELETE:
checkDeleteApplicable(modification, current);
+ break;
case TOUCH:
- checkSubtreeModificationApplicable(path, modification, current);
- return;
+ checkTouchApplicable(path, modification, current);
+ break;
case WRITE:
checkWriteApplicable(path, modification, current);
- return;
+ break;
case MERGE:
checkMergeApplicable(path, modification, current);
- return;
+ break;
case NONE:
- return;
+ break;
default:
- throw new UnsupportedOperationException("Suplied modification type "+ modification.getOperation()+ "is not supported.");
+ throw new UnsupportedOperationException("Suplied modification type "+ modification.getOperation()+ " is not supported.");
}
-
}
protected void checkMergeApplicable(final YangInstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
}
}
- boolean isOrdered() {
- return false;
+ @Override
+ protected ChildTrackingPolicy getChildPolicy() {
+ return ChildTrackingPolicy.UNORDERED;
}
@Override
- public final Optional<TreeNode> apply(final ModifiedNode modification,
- final Optional<TreeNode> currentMeta, final Version version) {
-
+ final Optional<TreeNode> apply(final ModifiedNode modification, final Optional<TreeNode> currentMeta, final Version version) {
switch (modification.getOperation()) {
case DELETE:
+ modification.resolveModificationType(ModificationType.DELETE);
return modification.setSnapshot(Optional.<TreeNode> absent());
case TOUCH:
Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
modification);
- return modification.setSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
+ return modification.setSnapshot(Optional.of(applyTouch(modification, currentMeta.get(),
version)));
case MERGE:
final TreeNode result;
if (currentMeta.isPresent()) {
result = applyMerge(modification,currentMeta.get(), version);
} else {
+ modification.resolveModificationType(ModificationType.WRITE);
result = applyWrite(modification, currentMeta, version);
}
return modification.setSnapshot(Optional.of(result));
case WRITE:
+ modification.resolveModificationType(ModificationType.WRITE);
return modification.setSnapshot(Optional.of(applyWrite(modification, currentMeta, version)));
case NONE:
+ modification.resolveModificationType(ModificationType.UNMODIFIED);
return currentMeta;
default:
throw new IllegalArgumentException("Provided modification type is not supported.");
}
}
- protected abstract TreeNode applyMerge(ModifiedNode modification,
- TreeNode currentMeta, Version version);
+ /**
+ * Apply a merge operation. Since the result of merge differs based on the data type
+ * being modified, implementations of this method are responsible for calling
+ * {@link ModifiedNode#resolveModificationType(ModificationType)} as appropriate.
+ *
+ * @param modification Modified node
+ * @param currentMeta Store Metadata Node on which NodeModification should be applied
+ * @param version New subtree version of parent node
+ * @return A sealed TreeNode representing applied operation.
+ */
+ protected abstract TreeNode applyMerge(ModifiedNode modification, TreeNode currentMeta, Version version);
- protected abstract TreeNode applyWrite(ModifiedNode modification,
- Optional<TreeNode> currentMeta, Version version);
+ protected abstract TreeNode applyWrite(ModifiedNode modification, Optional<TreeNode> currentMeta, Version version);
- protected abstract TreeNode applySubtreeChange(ModifiedNode modification,
- TreeNode currentMeta, Version version);
+ /**
+ * Apply a nested operation. Since there may not actually be a nested operation
+ * to be applied, implementations of this method are responsible for calling
+ * {@link ModifiedNode#resolveModificationType(ModificationType)} as appropriate.
+ *
+ * @param modification Modified node
+ * @param currentMeta Store Metadata Node on which NodeModification should be applied
+ * @param version New subtree version of parent node
+ * @return A sealed TreeNode representing applied operation.
+ */
+ protected abstract TreeNode applyTouch(ModifiedNode modification, TreeNode currentMeta, Version version);
/**
*
* @throws ConflictingModificationAppliedException If subtree was changed in conflicting way
* @throws IncorrectDataStructureException If subtree modification is not applicable (e.g. leaf node).
*/
- protected abstract void checkSubtreeModificationApplicable(YangInstanceIdentifier path, final NodeModification modification,
+ protected abstract void checkTouchApplicable(YangInstanceIdentifier path, final NodeModification modification,
final Optional<TreeNode> current) throws DataValidationFailedException;
protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class UnkeyedListItemModificationStrategy extends AbstractDataNodeContainerModificationStrategy<ListSchemaNode> {
+ UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
+ super(schemaNode, UnkeyedListEntryNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof UnkeyedListEntryNode);
+ return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
+ }
+}
\ No newline at end of file
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.IncorrectDataStructureException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNodeFactory;
private final Optional<ModificationApplyOperation> entryStrategy;
- protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
- entryStrategy = Optional.<ModificationApplyOperation> of(new DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy(schema));
+ UnkeyedListModificationStrategy(final ListSchemaNode schema) {
+ entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
}
@Override
- boolean isOrdered() {
- return true;
+ protected ChildTrackingPolicy getChildPolicy() {
+ return ChildTrackingPolicy.ORDERED;
}
@Override
protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
final Version version) {
+ modification.resolveModificationType(ModificationType.WRITE);
return applyWrite(modification, Optional.of(currentMeta), version);
}
@Override
- protected TreeNode applySubtreeChange(final ModifiedNode modification,
+ protected TreeNode applyTouch(final ModifiedNode modification,
final TreeNode currentMeta, final Version version) {
throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
}
}
@Override
- protected void checkSubtreeModificationApplicable(final YangInstanceIdentifier path, final NodeModification modification,
+ protected void checkTouchApplicable(final YangInstanceIdentifier path, final NodeModification modification,
final Optional<TreeNode> current) throws IncorrectDataStructureException {
throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
}
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Optional;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+final class UnorderedLeafSetModificationStrategy extends AbstractNodeContainerModificationStrategy {
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ super((Class) LeafSetNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof LeafSetNode<?>);
+ return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeWithValue) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Optional;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class UnorderedMapModificationStrategy extends AbstractNodeContainerModificationStrategy {
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ UnorderedMapModificationStrategy(final ListSchemaNode schema) {
+ super(MapNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof MapNode);
+ return ImmutableMapNodeBuilder.create((MapNode) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final YangInstanceIdentifier.PathArgument identifier) {
+ if (identifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public String toString() {
+ return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
+ }
+}
\ No newline at end of file
*
*/
final class UpgradableModificationApplyOperation extends RootModificationApplyOperation {
-
private final LatestOperationHolder holder;
private ModificationApplyOperation delegate;
- public UpgradableModificationApplyOperation(final LatestOperationHolder holder, final ModificationApplyOperation delegate) {
+ UpgradableModificationApplyOperation(final LatestOperationHolder holder, final ModificationApplyOperation delegate) {
this.holder = holder;
this.delegate = delegate;
-
}
@Override
- public void upgradeIfPossible() {
+ void upgradeIfPossible() {
ModificationApplyOperation holderCurrent = holder.getCurrent();
if (holderCurrent != delegate) {
// FIXME: Allow update only if there is addition of models, not
}
@Override
- public RootModificationApplyOperation snapshot() {
+ RootModificationApplyOperation snapshot() {
return new UpgradableModificationApplyOperation(holder, getDelegate());
}
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-public class SchemaAwareApplyOperationRoot extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
+public class SchemaAwareApplyOperationRoot extends AbstractDataNodeContainerModificationStrategy<ContainerSchemaNode> {
private final SchemaContext context;
public SchemaAwareApplyOperationRoot(final SchemaContext context) {
/*
* Copyright (c) 2013 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/epl-v10.html
package org.opendaylight.yangtools.yang.model.api;
import com.google.common.base.Optional;
-
import java.util.List;
/**
+/*
+ * 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/epl-v10.html
+ */
package org.opendaylight.yangtools.yang.model.api;
import com.google.common.base.Optional;
+/*
+ * 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/epl-v10.html
+ */
package org.opendaylight.yangtools.yang.model.api;
/**
-package org.opendaylight.yangtools.yang.model.api;
-
-import java.net.URI;
-import java.util.Date;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
+package org.opendaylight.yangtools.yang.model.api;
+
+import java.net.URI;
+import java.util.Date;
+
public interface NamespaceRevisionAware {
URI getNamespace();
-
/* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
public interface ModuleStatement extends DeclaredStatement<String>, ModuleHeaderGroup, LinkageGroup, MetaGroup,
- RevisionGroup, BodyGroup
-
- {
+ RevisionGroup, BodyGroup {
@Nonnull String getName();
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.CheckedFuture;
-
import java.util.Collection;
-
import javax.annotation.Nonnull;
-
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
/**
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.CheckedFuture;
-
import javax.annotation.Nonnull;
-
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
/**
private final Multimap<SourceIdentifier, ModuleImport> unsatisfiedImports;
private final Collection<SourceIdentifier> resolvedSources;
- public SchemaResolutionException(final @Nonnull String message) {
+ public SchemaResolutionException(@Nonnull final String message) {
this(message, (Throwable)null);
}
- public SchemaResolutionException(final @Nonnull String message, final Throwable cause) {
+ public SchemaResolutionException(@Nonnull final String message, final Throwable cause) {
this(message, cause, Collections.<SourceIdentifier>emptySet(), ImmutableMultimap.<SourceIdentifier, ModuleImport>of());
}
- public SchemaResolutionException(final @Nonnull String message, final Collection<SourceIdentifier> resolvedSources,
+ public SchemaResolutionException(@Nonnull final String message, final Collection<SourceIdentifier> resolvedSources,
final @Nonnull Multimap<SourceIdentifier, ModuleImport> unsatisfiedImports) {
this(message, null, resolvedSources, unsatisfiedImports);
}
- public SchemaResolutionException(final @Nonnull String message, final Throwable cause,
+ public SchemaResolutionException(@Nonnull final String message, final Throwable cause,
@Nonnull final Collection<SourceIdentifier> resolvedSources,
@Nonnull final Multimap<SourceIdentifier, ModuleImport> unsatisfiedImports) {
super(formatMessage(message, resolvedSources, unsatisfiedImports), cause);
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-
import java.util.Collections;
/**
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
import com.google.common.annotations.Beta;
-
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.concepts.Immutable;
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
import static com.google.common.base.Preconditions.checkArgument;
-
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.io.ByteSource;
-
import java.io.IOException;
import java.io.InputStream;
-
import org.opendaylight.yangtools.concepts.Delegator;
/**
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.api;
import com.google.common.annotations.Beta;
-
import org.w3c.dom.Document;
/**
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.spi;
import com.google.common.annotations.Beta;
-
import org.opendaylight.yangtools.concepts.ListenerRegistration;
/**
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.spi;
import com.google.common.annotations.Beta;
-
import java.util.EventListener;
-
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
/**
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.spi;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.CheckedFuture;
-
import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.spi;
import com.google.common.annotations.Beta;
-
import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
*
* 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
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.model.repo.spi;
import com.google.common.annotations.Beta;
-
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
final QName qname = Iterables.getFirst(schemaNode.getPath().getPathTowardsRoot(), null);
Preconditions.checkState(qname != null,
"Schema Path contains invalid state of path parts. " +
- "The Schema Path MUST contain at least ONE QName which defines namespace and Local name of path.");
+ "The Schema Path MUST contain at least ONE QName which defines namespace and Local name of path.");
return context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
}
RevisionAwareXPath pathStatement = typeDefinition.getPathStatement();
pathStatement = new RevisionAwareXPathImpl(stripConditionsFromXPathString(pathStatement), pathStatement.isAbsolute());
- final Module parentModule = SchemaContextUtil.findParentModule(schemaContext, schema);
+ Module parentModule = findParentModuleByType(schemaContext, schema);
final DataSchemaNode dataSchemaNode;
if(pathStatement.isAbsolute()) {
}
}
+ /**
+ * Returns parent Yang Module for specified Schema Context in which Schema
+ * Node is declared. If Schema Node is of type 'ExtendedType' it tries to find parent module
+ * in which the type was originally declared (needed for correct leafref path resolution). <br>
+ * If the Schema Node is not present in Schema Context the
+ * operation will return <code>null</code>. <br>
+ * If Schema Context or Schema Node contains <code>null</code> references
+ * the method will throw IllegalArgumentException
+ *
+ * @throws IllegalArgumentException
+ *
+ * @param schemaContext
+ * Schema Context
+ * @param schemaNode
+ * Schema Node
+ * @return Yang Module for specified Schema Context and Schema Node, if
+ * Schema Node is NOT present, the method will returns
+ * <code>null</code>
+ */
+ public static Module findParentModuleByType(final SchemaContext schemaContext, final SchemaNode schemaNode) {
+ Preconditions.checkArgument(schemaContext != null, "Schema Context reference cannot be NULL!");
+ Preconditions.checkArgument(schemaNode != null, "Schema Node cannot be NULL!");
+ TypeDefinition<?> nodeType = null;
+
+ if (schemaNode instanceof LeafSchemaNode) {
+ nodeType = ((LeafSchemaNode) schemaNode).getType();
+ } else if (schemaNode instanceof LeafListSchemaNode) {
+ nodeType = ((LeafListSchemaNode) schemaNode).getType();
+ }
+
+ if (nodeType != null && nodeType instanceof ExtendedType) {
+ while (nodeType.getBaseType() instanceof ExtendedType) {
+ nodeType = nodeType.getBaseType();
+ }
+
+ QNameModule typeDefModuleQname = nodeType.getQName().getModule();
+
+ return schemaContext.findModuleByNamespaceAndRevision(typeDefModuleQname.getNamespace(),
+ typeDefModuleQname.getRevision());
+ }
+
+ return SchemaContextUtil.findParentModule(schemaContext, schemaNode);
+ }
+
/**
* Returns base type for {@code typeDefinition} which belongs to module specified via {@code qName}. This handle case
* when leafref type isn't specified as type substatement of leaf or leaf-list but is defined in other module as typedef