From e1743c8eccee7d5ea8ad2c247d2575e8fd219fe4 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 12 Apr 2016 10:13:18 +0200 Subject: HONEYCOMB-9: Remove references to VPP from translation layer Change-Id: I281db366a112edc08203e8cb392a212708d4552a Signed-off-by: Maros Marsalek --- v3po/translate-api/pom.xml | 73 +++++++++++ .../io/fd/honeycomb/v3po/translate/Context.java | 49 ++++++++ .../honeycomb/v3po/translate/SubtreeManager.java | 39 ++++++ .../v3po/translate/TranslationException.java | 38 ++++++ .../v3po/translate/VppApiInvocationException.java | 76 ++++++++++++ .../honeycomb/v3po/translate/read/ChildReader.java | 50 ++++++++ .../honeycomb/v3po/translate/read/ListReader.java | 47 +++++++ .../honeycomb/v3po/translate/read/ReadContext.java | 37 ++++++ .../v3po/translate/read/ReadFailedException.java | 61 ++++++++++ .../fd/honeycomb/v3po/translate/read/Reader.java | 51 ++++++++ .../v3po/translate/read/ReaderRegistry.java | 43 +++++++ .../v3po/translate/write/ChildWriter.java | 66 ++++++++++ .../v3po/translate/write/WriteContext.java | 60 +++++++++ .../fd/honeycomb/v3po/translate/write/Writer.java | 49 ++++++++ .../v3po/translate/write/WriterRegistry.java | 135 +++++++++++++++++++++ .../v3po/translate/ReadFailedExceptionTest.java | 50 ++++++++ .../translate/VppApiInvocationExceptionTest.java | 44 +++++++ 17 files changed, 968 insertions(+) create mode 100644 v3po/translate-api/pom.xml create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/Context.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/SubtreeManager.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/TranslationException.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ChildReader.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ListReader.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadContext.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadFailedException.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/Reader.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReaderRegistry.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteContext.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java create mode 100644 v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/ReadFailedExceptionTest.java create mode 100644 v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java (limited to 'v3po/translate-api') diff --git a/v3po/translate-api/pom.xml b/v3po/translate-api/pom.xml new file mode 100644 index 000000000..42501e752 --- /dev/null +++ b/v3po/translate-api/pom.xml @@ -0,0 +1,73 @@ + + + + + io.fd.honeycomb.common + api-parent + 1.0.0-SNAPSHOT + ../../common/api-parent + + + 4.0.0 + io.fd.honeycomb.v3po + translate-api + 1.0.0-SNAPSHOT + bundle + + + + + org.opendaylight.mdsal + mdsal-artifacts + 2.0.0-Beryllium + pom + import + + + + + + + com.google.guava + guava + + + org.opendaylight.mdsal + mdsal-binding-api + + + + + ${project.groupId} + v3po-api + ${project.version} + test + + + junit + junit + test + + + org.mockito + mockito-all + test + + + + + diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/Context.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/Context.java new file mode 100644 index 000000000..b60963678 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/Context.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate; + +import com.google.common.collect.Maps; +import java.util.HashMap; + +/** + * Simple context class that provides transient storage during one or more read/write operations + */ +public class Context implements AutoCloseable { + + protected final HashMap map; + + public Context() { + map = Maps.newHashMap(); + } + + public Object get(final Object o) { + return map.get(o); + } + + public boolean containsKey(final Object o) { + return map.containsKey(o); + } + + public Object put(final Object o, final Object o2) { + return map.put(o, o2); + } + + @Override + public void close() { + map.clear(); + } +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/SubtreeManager.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/SubtreeManager.java new file mode 100644 index 000000000..39e403642 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/SubtreeManager.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate; + +import com.google.common.annotations.Beta; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Base identifiable subtree manager(reader, writer etc.) + * + * @param Specific DataObject derived type, that is managed by this manager + */ +@Beta +public interface SubtreeManager { + + /** + * Gets the type of node managed by this reader + * + * @return Class object for node managed by this reader + */ + @Nonnull + InstanceIdentifier getManagedDataObjectType(); +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/TranslationException.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/TranslationException.java new file mode 100644 index 000000000..ee0049977 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/TranslationException.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate; + +import com.google.common.annotations.Beta; + +/** + * Base exception for the translation layer + */ +@Beta +public class TranslationException extends Exception { + + public TranslationException(final String s) { + super(s); + } + + public TranslationException(final String s, final Throwable cause) { + super(s, cause); + } + + public TranslationException(final Throwable cause) { + super(cause); + } +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java new file mode 100644 index 000000000..298c698f7 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import javax.annotation.Nonnull; + +/** + * Thrown when Vpp jAPI method invocation failed. + */ +@Beta +public class VppApiInvocationException extends TranslationException { + private final String methodName; + private final int ctxId; + private final int errorCode; + + /** + * Constructs an VppApiInvocationFailedException with the specified api method name and error code. + * + * @param methodName method name that failed to invoke + * @param ctxId api request context identifier + * @param errorCode negative error code value associated with this failure + * @throws NullPointerException if apiMethodName is null + * @throws IllegalArgumentException if errorCode is nonnegative + */ + public VppApiInvocationException(@Nonnull final String methodName, final int ctxId, final int errorCode) { + super(String.format("vppApi.%s failed with error code: %d (ctxId=%d) ", methodName, errorCode, ctxId)); + this.methodName = Preconditions.checkNotNull(methodName, "apiMethodName is null!"); + this.ctxId = ctxId; + Preconditions.checkArgument(errorCode < 0); + this.errorCode = errorCode; + } + + /** + * Returns method name that failed to invoke. + * + * @return method name + */ + public String getMethodName() { + return methodName; + } + + /** + * Returns api request context identifier. + * + * @return value of context identifier + */ + public int getCtxId() { + return ctxId; + } + + /** + * Returns the error code associated with this failure. + * + * @return a negative integer error code + */ + public int getErrorCode() { + return errorCode; + } +} + diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ChildReader.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ChildReader.java new file mode 100644 index 000000000..02b6b8d26 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ChildReader.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.read; + +import com.google.common.annotations.Beta; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Child reader allowing its parent to pass the builder object + * + * @param Specific DataObject derived type, that is handled by this reader + */ +@Beta +public interface ChildReader extends Reader { + + /** + * Reads subtree starting from node managed by this reader and place the subtree within parent builder object if the + * data exists. + * + * @param id Unique identifier pointing to the node managed by this reader. Useful when necessary to + * determine the exact position within more complex subtrees. + * @param parentBuilder Builder of parent DataObject. Objects read on this level (if any) must be placed into the + * parent builder. + * @param ctx Read context + * + * @throws ReadFailedException if read was unsuccessful + */ + void read(@Nonnull final InstanceIdentifier id, + @Nonnull final Builder parentBuilder, + @Nonnull final ReadContext ctx) throws ReadFailedException; + +} + diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ListReader.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ListReader.java new file mode 100644 index 000000000..faf6f0a19 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ListReader.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.read; + +import com.google.common.annotations.Beta; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifiable; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * List reader, allowing read of all the elements + * + * @param Specific DataObject derived type, that is handled by this reader + */ +@Beta +public interface ListReader, K extends Identifier> extends Reader { + + /** + * Read all elements in this list + * + * @param id Wildcarded identifier of list managed by this reader + * @param ctx Read context + * + * @return List of all entries in this list + * @throws ReadFailedException if read was unsuccessful + */ + @Nonnull + List readList(@Nonnull final InstanceIdentifier id, + @Nonnull final ReadContext ctx) throws ReadFailedException; +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadContext.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadContext.java new file mode 100644 index 000000000..6b1473548 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadContext.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.read; + +import io.fd.honeycomb.v3po.translate.Context; +import javax.annotation.Nonnull; + +/** + * Read Context + */ +public interface ReadContext extends AutoCloseable { + + /** + * Get key value storage for customizers + * + * @return Context for customizers + */ + @Nonnull + Context getContext(); + + @Override + void close(); +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadFailedException.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadFailedException.java new file mode 100644 index 000000000..51d4fcb5a --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReadFailedException.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.read; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.honeycomb.v3po.translate.TranslationException; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Thrown when a reader or customizer is not able to read data for the given id. + */ +public class ReadFailedException extends TranslationException { + + private final InstanceIdentifier failedId; + + /** + * Constructs an ReadFailedException given data id and exception cause. + * + * @param failedId instance identifier of the data object that could not be read + * @param cause the cause of read failure + */ + public ReadFailedException(@Nonnull final InstanceIdentifier failedId, final Throwable cause) { + super("Failed to read " + failedId, cause); + this.failedId = checkNotNull(failedId, "failedId should not be null"); + } + + /** + * Constructs an ReadFailedException given data id. + * + * @param failedId instance identifier of the data object that could not be read + */ + public ReadFailedException(@Nonnull final InstanceIdentifier failedId) { + this(failedId, null); + } + + /** + * Returns id of the data object that could not be read. + * + * @return data object instance identifier + */ + @Nonnull + public InstanceIdentifier getFailedId() { + return failedId; + } +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/Reader.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/Reader.java new file mode 100644 index 000000000..122263cb3 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/Reader.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.read; + +import com.google.common.annotations.Beta; +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.SubtreeManager; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Base reader, responsible for translation between DataObjects and any other side + * + * @param Specific DataObject derived type, that is handled by this reader + */ +@Beta +public interface Reader extends SubtreeManager { + + // TODO make async + + /** + * Reads data identified by id + * + * @param id unique identifier of subtree to be read. The subtree must contain managed data object type. For + * identifiers pointing below node managed by this reader, it's reader's responsibility to filter out the + * right node or to delegate the read to a child reader. + * @param ctx Read context + * + * @return List of DataObjects identified by id. If the ID points to a single node, it will be wrapped in a list + * @throws ReadFailedException if read was unsuccessful + */ + @Nonnull + Optional read(@Nonnull final InstanceIdentifier id, + @Nonnull ReadContext ctx) throws ReadFailedException; + +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReaderRegistry.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReaderRegistry.java new file mode 100644 index 000000000..f34455a27 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/read/ReaderRegistry.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.read; + +import com.google.common.annotations.Beta; +import com.google.common.collect.Multimap; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Simple delegating reader suitable as a holder for all other root readers, providing readAll feature. + */ +@Beta +public interface ReaderRegistry extends Reader { + + /** + * Performs read on all registered root readers and merges the results into a Multimap. Keys represent identifiers + * for root DataObjects from the data tree modeled by YANG. + * + * @param ctx Read context + * + * @return multimap that preserves deterministic iteration order across non-distinct key values + * @throws ReadFailedException if read was unsuccessful + */ + @Nonnull + Multimap, ? extends DataObject> readAll(@Nonnull final ReadContext ctx) + throws ReadFailedException; +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java new file mode 100644 index 000000000..f933cfd4a --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.write; + +import com.google.common.annotations.Beta; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Child writer allowing its parent to pass the builder object + * + * @param Specific DataObject derived type, that is handled by this writer + */ +@Beta +public interface ChildWriter extends Writer { + + /** + * Extract data object managed by this writer from parent data and perform write. + * + * @param parentId Id of parent node + * @param parentDataAfter Parent data from modification to extract data object from + * @param ctx Write context for current modification + */ + void writeChild(@Nonnull final InstanceIdentifier parentId, + @Nonnull final DataObject parentDataAfter, + @Nonnull final WriteContext ctx); + + /** + * Extract data object managed by this writer(if necessary) from parent data and perform delete. + * + * @param parentId Id of parent node + * @param parentDataBefore Parent data before modification to extract data object from + * @param ctx Write context for current modification + */ + void deleteChild(@Nonnull final InstanceIdentifier parentId, + @Nonnull final DataObject parentDataBefore, + @Nonnull final WriteContext ctx); + + /** + * Extract data object managed by this writer(if necessary) from parent data and perform delete. + * + * @param parentId Id of parent node + * @param parentDataBefore Parent data before modification to extract data object from + * @param parentDataAfter Parent data from modification to extract data object from + * @param ctx Write context for current modification + */ + void updateChild(@Nonnull final InstanceIdentifier parentId, + @Nonnull final DataObject parentDataBefore, + @Nonnull final DataObject parentDataAfter, + @Nonnull final WriteContext ctx); +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteContext.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteContext.java new file mode 100644 index 000000000..bb0b33145 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteContext.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.write; + +import com.google.common.annotations.Beta; +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Context providing information about current state of DataTree to writers + */ +@Beta +public interface WriteContext extends AutoCloseable { + + /** + * Read any data object before current modification was applied + * + * @param currentId Id of an object to read + * + * @return Data before the modification was applied + */ + Optional readBefore(@Nonnull final InstanceIdentifier currentId); + + /** + * Read any data object from current modification + * + * @param currentId Id of an object to read + * + * @return Data from the modification + */ + Optional readAfter(@Nonnull final InstanceIdentifier currentId); + + /** + * Get key value storage for customizers + * + * @return Context for customizers + */ + @Nonnull + Context getContext(); + + @Override + void close(); +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java new file mode 100644 index 000000000..08465fdd7 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.write; + +import com.google.common.annotations.Beta; +import io.fd.honeycomb.v3po.translate.TranslationException; +import io.fd.honeycomb.v3po.translate.SubtreeManager; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Base writer, responsible for translation between DataObjects and any other side. Handling all update operations(create, + * update, delete) + * + * @param Specific DataObject derived type, that is handled by this writer + */ +@Beta +public interface Writer extends SubtreeManager { + + /** + * Handle update operation. U from CRUD. + * + * @param id Identifier(from root) of data being written + * @param dataBefore Old data + * @param dataAfter New, updated data + * @param ctx Write context enabling writer to get information about candidate data as well as current data + * @throws TranslationException if update failed + */ + void update(@Nonnull final InstanceIdentifier id, + @Nullable final DataObject dataBefore, + @Nullable final DataObject dataAfter, + @Nonnull final WriteContext ctx) throws TranslationException; +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java new file mode 100644 index 000000000..c5a8116c8 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.write; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableList; +import io.fd.honeycomb.v3po.translate.TranslationException; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Special {@link Writer} capable of performing bulk updates + */ +@Beta +public interface WriterRegistry extends Writer { + + /** + * Performs bulk update + * + * @throws BulkUpdateException in case bulk update fails + * @throws TranslationException in case some other error occurs while processing update request + */ + void update(@Nonnull final Map, DataObject> dataBefore, + @Nonnull final Map, DataObject> dataAfter, + @Nonnull final WriteContext ctx) throws TranslationException; + + /** + * Thrown when bulk update failed. + */ + @Beta + class BulkUpdateException extends TranslationException { + + private final Reverter reverter; + private final InstanceIdentifier failedId; // TODO change to VppDataModification + + /** + * Constructs an BulkUpdateException. + * + * @param failedId instance identifier of the data object that caused bulk update to fail. + * @param cause the cause of bulk update failure + */ + public BulkUpdateException(@Nonnull final InstanceIdentifier failedId, @Nonnull final Reverter reverter, + final Throwable cause) { + super("Bulk update failed at " + failedId, cause); + this.failedId = checkNotNull(failedId, "failedId should not be null"); + this.reverter = checkNotNull(reverter, "reverter should not be null"); + } + + /** + * Reverts changes that were successfully applied during bulk update before failure occurred. + * + * @throws Reverter.RevertFailedException if revert fails + */ + public void revertChanges() throws Reverter.RevertFailedException { + reverter.revert(); + } + + /** + * Returns instance identifier of the data object that caused bulk update to fail. + * + * @return data object's instance identifier + */ + @Nonnull + public InstanceIdentifier getFailedId() { + return failedId; + } + } + + /** + * Abstraction over revert mechanism in cast of a bulk update failure + */ + @Beta + interface Reverter { + + /** + * Reverts changes that were successfully applied during bulk update before failure occurred. Changes are + * reverted in reverse order they were applied. + * + * @throws RevertFailedException if not all of applied changes were successfully reverted + */ + void revert() throws RevertFailedException; + + /** + * Thrown when some of the changes applied during bulk update were not reverted. + */ + @Beta + class RevertFailedException extends TranslationException { + + // TODO change to list of VppDataModifications to make debugging easier + private final List> notRevertedChanges; + + /** + * Constructs an RevertFailedException with the list of changes that were not reverted. + * + * @param notRevertedChanges list of changes that were not reverted + * @param cause the cause of revert failure + */ + public RevertFailedException(@Nonnull final List> notRevertedChanges, + final Throwable cause) { + super(cause); + checkNotNull(notRevertedChanges, "notRevertedChanges should not be null"); + this.notRevertedChanges = ImmutableList.copyOf(notRevertedChanges); + } + + /** + * Returns the list of changes that were not reverted. + * + * @return list of changes that were not reverted + */ + @Nonnull + public List> getNotRevertedChanges() { + return notRevertedChanges; + } + } + } +} \ No newline at end of file diff --git a/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/ReadFailedExceptionTest.java b/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/ReadFailedExceptionTest.java new file mode 100644 index 000000000..71c0afbd3 --- /dev/null +++ b/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/ReadFailedExceptionTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate; + +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class ReadFailedExceptionTest { + + @Test + public void testInstantiation() { + final InstanceIdentifier id = InstanceIdentifier.create(DataObject.class); + ReadFailedException e = new ReadFailedException(id); + Assert.assertEquals(id, e.getFailedId()); + Assert.assertNull(e.getCause()); + Assert.assertTrue(e.getMessage().contains(id.toString())); + } + + @Test + public void testInstantiationWithCause() { + final InstanceIdentifier id = InstanceIdentifier.create(DataObject.class); + final RuntimeException cause = new RuntimeException(); + ReadFailedException e = new ReadFailedException(id, cause); + Assert.assertEquals(id, e.getFailedId()); + Assert.assertEquals(cause, e.getCause()); + Assert.assertTrue(e.getMessage().contains(id.toString())); + } + + @Test(expected = NullPointerException.class) + public void testInstantiationFailed() { + new ReadFailedException(null); + } +} \ No newline at end of file diff --git a/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java b/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java new file mode 100644 index 000000000..b2cfbd216 --- /dev/null +++ b/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate; + +import java.util.Random; +import org.junit.Assert; +import org.junit.Test; + +public class VppApiInvocationExceptionTest { + + @Test + public void testInstantiation() { + final String apiMethodName = "methodName"; + final int ctxId = 1; + final int code = -1; + VppApiInvocationException e = new VppApiInvocationException(apiMethodName, ctxId, code); + Assert.assertEquals(apiMethodName, e.getMethodName()); + Assert.assertEquals(ctxId, e.getCtxId()); + Assert.assertEquals(code, e.getErrorCode()); + Assert.assertTrue(e.getMessage().contains(apiMethodName)); + Assert.assertTrue(e.getMessage().contains(String.valueOf(code))); + Assert.assertTrue(e.getMessage().contains(String.valueOf(ctxId))); + } + + @Test(expected = IllegalArgumentException.class) + public void testInstantiationFailed() { + final int code = new Random().nextInt(Integer.MAX_VALUE); + VppApiInvocationException e = new VppApiInvocationException("apiMethodName", 1, code); + } +} -- cgit 1.2.3-korg