import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerLike;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCodecContext<D,SchemaContext> {
- private final LoadingCache<Class<?>, DataContainerCodecContext<?,?>> childrenByClass = CacheBuilder.newBuilder()
- .build(new CacheLoader<Class<?>, DataContainerCodecContext<?,?>>() {
- @Override
- public DataContainerCodecContext<?,?> load(final Class<?> key) {
- return createDataTreeChildContext(key);
- }
- });
-
- private final LoadingCache<Class<? extends Action<?, ?, ?>>, ActionCodecContext> actionsByClass = CacheBuilder
- .newBuilder().build(new CacheLoader<Class<? extends Action<?, ?, ?>>, ActionCodecContext>() {
- @Override
- public ActionCodecContext load(final Class<? extends Action<?, ?, ?>> key) {
- return createActionContext(key);
+ private final LoadingCache<Class<? extends DataObject>, DataContainerCodecContext<?, ?>> childrenByClass =
+ CacheBuilder.newBuilder().build(new CacheLoader<>() {
+ @Override
+ public DataContainerCodecContext<?, ?> load(final Class<? extends DataObject> key) {
+ if (Notification.class.isAssignableFrom(key)) {
+ return createNotificationDataContext(key);
}
- });
-
- private final LoadingCache<Class<?>, ContainerNodeCodecContext<?>> rpcDataByClass = CacheBuilder.newBuilder().build(
- new CacheLoader<Class<?>, ContainerNodeCodecContext<?>>() {
- @Override
- public ContainerNodeCodecContext<?> load(final Class<?> key) {
+ if (RpcInput.class.isAssignableFrom(key) || RpcOutput.class.isAssignableFrom(key)) {
return createRpcDataContext(key);
}
- });
+ return createDataTreeChildContext(key);
+ }
+ });
- private final LoadingCache<Class<?>, NotificationCodecContext<?>> notificationsByClass = CacheBuilder.newBuilder()
- .build(new CacheLoader<Class<?>, NotificationCodecContext<?>>() {
- @Override
- public NotificationCodecContext<?> load(final Class<?> key) {
- return createNotificationDataContext(key);
- }
- });
+ private final LoadingCache<Class<? extends Action<?, ?, ?>>, ActionCodecContext> actionsByClass =
+ CacheBuilder.newBuilder().build(new CacheLoader<>() {
+ @Override
+ public ActionCodecContext load(final Class<? extends Action<?, ?, ?>> key) {
+ return createActionContext(key);
+ }
+ });
private final LoadingCache<Class<? extends DataObject>, ChoiceNodeCodecContext<?>> choicesByClass =
- CacheBuilder.newBuilder().build(new CacheLoader<Class<? extends DataObject>, ChoiceNodeCodecContext<?>>() {
- @Override
- public ChoiceNodeCodecContext<?> load(final Class<? extends DataObject> key) {
- return createChoiceDataContext(key);
- }
- });
-
- private final LoadingCache<QName, DataContainerCodecContext<?,?>> childrenByQName = CacheBuilder.newBuilder().build(
- new CacheLoader<QName, DataContainerCodecContext<?,?>>() {
- @Override
- public DataContainerCodecContext<?,?> load(final QName qname) {
- final DataSchemaNode childSchema = getSchema().getDataChildByName(qname);
- childNonNull(childSchema, qname,"Argument %s is not valid child of %s", qname,getSchema());
- if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
- @SuppressWarnings("unchecked")
- final Class<? extends DataObject> childCls = (Class<? extends DataObject>)
- factory().getRuntimeContext().getClassForSchema(childSchema);
- return streamChild(childCls);
- }
-
- throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
+ CacheBuilder.newBuilder().build(new CacheLoader<>() {
+ @Override
+ public ChoiceNodeCodecContext<?> load(final Class<? extends DataObject> key) {
+ return createChoiceDataContext(key);
+ }
+ });
+
+ private final LoadingCache<QName, DataContainerCodecContext<?,?>> childrenByQName =
+ CacheBuilder.newBuilder().build(new CacheLoader<>() {
+ @Override
+ public DataContainerCodecContext<?, ?> load(final QName qname) {
+ final DataSchemaNode childSchema = getSchema().getDataChildByName(qname);
+ childNonNull(childSchema, qname, "Argument %s is not valid child of %s", qname, getSchema());
+ if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
+ @SuppressWarnings("unchecked")
+ final Class<? extends DataObject> childCls = (Class<? extends DataObject>)
+ factory().getRuntimeContext().getClassForSchema(childSchema);
+ return streamChild(childCls);
}
- });
- private final LoadingCache<Absolute, RpcInputCodec<?>> rpcDataByPath = CacheBuilder.newBuilder().build(
- new CacheLoader<Absolute, RpcInputCodec<?>>() {
+ throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
+ }
+ });
+
+ private final LoadingCache<Absolute, RpcInputCodec<?>> rpcDataByPath =
+ CacheBuilder.newBuilder().build(new CacheLoader<>() {
@Override
public RpcInputCodec<?> load(final Absolute key) {
- final ContainerSchemaNode schema = SchemaContextUtil.getRpcDataSchema(getSchema(), key.asSchemaPath());
+ final ContainerLike schema = SchemaContextUtil.getRpcDataSchema(getSchema(), key.asSchemaPath());
@SuppressWarnings("unchecked")
final Class<? extends DataContainer> cls = (Class<? extends DataContainer>)
- factory().getRuntimeContext().getClassForSchema(schema);
+ factory().getRuntimeContext().getClassForSchema(schema);
return getRpc(cls);
}
});
- private final LoadingCache<Absolute, NotificationCodecContext<?>> notificationsByPath = CacheBuilder.newBuilder()
- .build(new CacheLoader<Absolute, NotificationCodecContext<?>>() {
- @Override
- public NotificationCodecContext<?> load(final Absolute key) {
- final NotificationDefinition schema = SchemaContextUtil.getNotificationSchema(getSchema(),
- // FIXME: do not convert here!
- key.asSchemaPath());
- @SuppressWarnings("unchecked")
- final Class<? extends Notification> clz = (Class<? extends Notification>)
- factory().getRuntimeContext().getClassForSchema(schema);
- return getNotification(clz);
- }
- });
+ private final LoadingCache<Absolute, NotificationCodecContext<?>> notificationsByPath =
+ CacheBuilder.newBuilder().build(new CacheLoader<>() {
+ @Override
+ public NotificationCodecContext<?> load(final Absolute key) {
+ final NotificationDefinition schema = SchemaContextUtil.getNotificationSchema(getSchema(),
+ // FIXME: do not convert here!
+ key.asSchemaPath());
+ @SuppressWarnings("unchecked")
+ final Class<? extends Notification> clz = (Class<? extends Notification>)
+ factory().getRuntimeContext().getClassForSchema(schema);
+ return getNotification(clz);
+ }
+ });
private SchemaRootCodecContext(final DataContainerCodecPrototype<SchemaContext> dataPrototype) {
super(dataPrototype);
@SuppressWarnings("unchecked")
@Override
public <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(final Class<C> 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<C, ?>) getNotification((Class<? extends Notification>)childClass);
- }
- return (DataContainerCodecContext<C, ?>) getOrRethrow(childrenByClass,childClass);
+ return (DataContainerCodecContext<C, ?>) getOrRethrow(childrenByClass, childClass);
}
@Override
}
NotificationCodecContext<?> getNotification(final Class<? extends Notification> notification) {
- return getOrRethrow(notificationsByClass, notification);
+ return (NotificationCodecContext<?>) streamChild((Class<? extends DataObject>)notification);
}
NotificationCodecContext<?> getNotification(final Absolute notification) {
}
ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
- return getOrRethrow(rpcDataByClass, rpcInputOrOutput);
+ return (ContainerNodeCodecContext<?>) streamChild((Class<? extends DataObject>)rpcInputOrOutput);
}
RpcInputCodec<?> getRpc(final Absolute containerPath) {
* FIXME: Rework this to have more precise logic regarding Binding Specification.
*/
if (key.getSimpleName().equals(BindingMapping.getClassName(potentialQName) + className)) {
- final ContainerSchemaNode schema = SchemaNodeUtils.getRpcDataSchema(potential, qname);
+ final ContainerLike schema = SchemaNodeUtils.getRpcDataSchema(potential, qname);
checkArgument(schema != null, "Schema for %s does not define input / output.", potential.getQName());
return (ContainerNodeCodecContext<?>) DataContainerCodecPrototype.from(key, schema, factory()).get();
}
final List<PathArgument> builder) {
final Optional<? extends Class<? extends DataObject>> caseType = arg.getCaseType();
if (caseType.isPresent()) {
- // XXX: we use two caseType.get()s because of https://bugs.openjdk.java.net/browse/JDK-8144185,
- // which makes JaCoCo blow up if we try using @NonNull on the local variable.
- final ChoiceNodeCodecContext<?> choice = choicesByClass.getUnchecked(caseType.get());
+ final @NonNull Class<? extends DataObject> type = caseType.orElseThrow();
+ final ChoiceNodeCodecContext<?> choice = choicesByClass.getUnchecked(type);
choice.addYangPathArgument(arg, builder);
- final DataContainerCodecContext<?, ?> caze = choice.streamChild(caseType.get());
+ final DataContainerCodecContext<?, ?> caze = choice.streamChild(type);
caze.addYangPathArgument(arg, builder);
return caze.bindingPathArgumentChild(arg, builder);
}