import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
+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.model.api.ChoiceSchemaNode;
@Override
public DataContainerCodecContext<?,?> load(final QName qname) {
final DataSchemaNode childSchema = schema().getDataChildByName(qname);
- Preconditions.checkArgument(childSchema != null, "Argument %s is not valid child of %s", qname,
- schema());
-
+ childNonNull(childSchema, qname,"Argument %s is not valid child of %s", qname,schema());
if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
@SuppressWarnings("rawtypes")
final Class childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
@SuppressWarnings("unchecked")
@Override
- public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(Class<DV> childClass)
+ public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass)
throws IllegalArgumentException {
- return (DataContainerCodecContext<DV, ?>) childrenByClass.getUnchecked(childClass);
+ /* FIXME: This is still not solved for RPCs
+ * TODO: Probably performance wise RPC, Data and Notification loading cache
+ * should be merge for performance resons. Needs microbenchmark to
+ * determine which is faster (keeping them separate or in same cache).
+ */
+ if (Notification.class.isAssignableFrom(childClass)) {
+ return (DataContainerCodecContext<DV, ?>) getNotification((Class<? extends Notification>)childClass);
+ }
+ return (DataContainerCodecContext<DV, ?>) getOrRethrow(childrenByClass,childClass);
}
@Override
@Override
public DataContainerCodecContext<?,?> yangPathArgumentChild(final PathArgument arg) {
- return childrenByQName.getUnchecked(arg.getNodeType());
+ return getOrRethrow(childrenByQName,arg.getNodeType());
}
@Override
ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
- return rpcDataByClass.getUnchecked(rpcInputOrOutput);
+ return getOrRethrow(rpcDataByClass, rpcInputOrOutput);
}
NotificationCodecContext<?> getNotification(final Class<? extends Notification> notification) {
- return notificationsByClass.getUnchecked(notification);
+ return getOrRethrow(notificationsByClass, notification);
}
NotificationCodecContext<?> getNotification(final SchemaPath notification) {
- return notificationsByPath.getUnchecked(notification);
+ return getOrRethrow(notificationsByPath, notification);
}
ContainerNodeCodecContext<?> getRpc(final SchemaPath notification) {
- return rpcDataByPath.getUnchecked(notification);
+ return getOrRethrow(rpcDataByPath, notification);
}
private DataContainerCodecContext<?,?> createDataTreeChildContext(final Class<?> key) {
final Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
- Preconditions.checkArgument(DataRoot.class.isAssignableFrom(parent));
+ IncorrectNestingException.check(DataRoot.class.isAssignableFrom(parent), "Class %s is not top level item.", key);
final QName qname = BindingReflections.findQName(key);
- final DataSchemaNode childSchema = schema().getDataChildByName(qname);
+ final DataSchemaNode childSchema = childNonNull(schema().getDataChildByName(qname),key,"%s is not top-level item.",key);
return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
}
}
@Override
- protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+ protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
throw new UnsupportedOperationException("Unable to deserialize root");
}
+ @Override
+ public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
+ Preconditions.checkArgument(arg == null);
+ return null;
+ }
+
+ @Override
+ public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
+ Preconditions.checkArgument(arg == null);
+ return null;
+ }
+
+ private static <K,V> V getOrRethrow(final LoadingCache<K, V> cache, final K key) {
+ try {
+ return cache.getUnchecked(key);
+ } catch (final UncheckedExecutionException e) {
+ final Throwable cause = e.getCause();
+ if(cause != null) {
+ Throwables.propagateIfPossible(cause);
+ }
+ throw e;
+ }
+ }
+
}
\ No newline at end of file