Repository: incubator-reef Updated Branches: refs/heads/REEF-395 [created] ba431c456
[REEF-395] Implement ClassHierarchySerializer using Avro on the Java side  This addressed the issue by   * Defining the avro schema for class hierarchy   * Implementing the AvroClassHierarchy * Define ClassHierarchySerializer interface and implement an Avro version * Rewrite the test code to use serializer * Replace the class hierarchy serializer for the round trip tests * Leave TODO comments for the future issues to resolve when we revisit REEF-148 JIRA: [REEF-395](https://issues.apache.org/jira/browse/REEF-395) Project: http://git-wip-us.apache.org/repos/asf/incubator-reef/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-reef/commit/cb901a66 Tree: http://git-wip-us.apache.org/repos/asf/incubator-reef/tree/cb901a66 Diff: http://git-wip-us.apache.org/repos/asf/incubator-reef/diff/cb901a66 Branch: refs/heads/REEF-395 Commit: cb901a6623a085dbd85b542ca2150db35f17b375 Parents: 2b374df Author: Yunseong Lee <[email protected]> Authored: Fri Jun 19 17:22:11 2015 +0900 Committer: Yunseong Lee <[email protected]> Committed: Tue Jun 23 01:03:31 2015 +0900 ---------------------------------------------------------------------- .../org/apache/reef/javabridge/Utilities.java | 2 + .../reef/examples/helloCLR/HelloDriver.java | 2 + .../serialization/NamingLookupRequestCodec.java | 2 +- .../tang/src/main/avro/class_hierarchy.avsc | 120 ++++ .../org/apache/reef/tang/ClassHierarchy.java | 1 - .../formats/AvroClassHierarchySerializer.java | 255 +++++++++ .../tang/formats/ClassHierarchySerializer.java | 79 +++ .../implementation/java/AvroClassHierarchy.java | 200 +++++++ .../protobuf/ProtocolBufferClassHierarchy.java | 1 + .../reef/tang/util/ValidateConfiguration.java | 2 + .../tang/ClassHierarchyDeserializationTest.java | 24 +- .../formats/TestClassHierarchyRoundTrip.java | 551 +++++++++++++++++++ .../protobuf/TestClassHierarchyRoundTrip.java | 401 -------------- .../apache/reef/tang/test/RoundTripTest.java | 6 +- pom.xml | 3 + 15 files changed, 1237 insertions(+), 412 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/Utilities.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/Utilities.java b/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/Utilities.java index 93b6903..88307cf 100644 --- a/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/Utilities.java +++ b/lang/java/reef-bridge-java/src/main/java/org/apache/reef/javabridge/Utilities.java @@ -33,6 +33,7 @@ import java.nio.file.Paths; public class Utilities { public static ClassHierarchy loadClassHierarchy(String classHierarchyFile) { + // TODO The file should be created via AvroClassHierarchySerializer Path p = Paths.get(classHierarchyFile); if (!Files.exists(p)) { p = Paths.get(System.getProperty("user.dir") + "/reef/global/" + classHierarchyFile); @@ -40,6 +41,7 @@ public class Utilities { if (!Files.exists(p)) { throw new RuntimeException("cannot find file " + p.toAbsolutePath()); } + // TODO Use the AvroClassHierarchy in place of protobuf try (final InputStream chin = new FileInputStream(p.toAbsolutePath().toString())) { final ClassHierarchyProto.Node root = ClassHierarchyProto.Node.parseFrom(chin); final ClassHierarchy ch = new ProtocolBufferClassHierarchy(root); http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-examples-clr/src/main/java/org/apache/reef/examples/helloCLR/HelloDriver.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-examples-clr/src/main/java/org/apache/reef/examples/helloCLR/HelloDriver.java b/lang/java/reef-examples-clr/src/main/java/org/apache/reef/examples/helloCLR/HelloDriver.java index 18f4623..29b3126 100644 --- a/lang/java/reef-examples-clr/src/main/java/org/apache/reef/examples/helloCLR/HelloDriver.java +++ b/lang/java/reef-examples-clr/src/main/java/org/apache/reef/examples/helloCLR/HelloDriver.java @@ -92,7 +92,9 @@ public final class HelloDriver { * @return */ private static ClassHierarchy loadClassHierarchy() { + // TODO The file should be created by AvroClassHierarchySerializer try (final InputStream chin = new FileInputStream(HelloCLR.CLASS_HIERARCHY_FILENAME)) { + // TODO Use AvroClassHierarchySerializer instead final ClassHierarchyProto.Node root = ClassHierarchyProto.Node.parseFrom(chin); // A final ClassHierarchy ch = new ProtocolBufferClassHierarchy(root); return ch; http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-io/src/main/java/org/apache/reef/io/network/naming/serialization/NamingLookupRequestCodec.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-io/src/main/java/org/apache/reef/io/network/naming/serialization/NamingLookupRequestCodec.java b/lang/java/reef-io/src/main/java/org/apache/reef/io/network/naming/serialization/NamingLookupRequestCodec.java index da8b47a..b7261b4 100644 --- a/lang/java/reef-io/src/main/java/org/apache/reef/io/network/naming/serialization/NamingLookupRequestCodec.java +++ b/lang/java/reef-io/src/main/java/org/apache/reef/io/network/naming/serialization/NamingLookupRequestCodec.java @@ -52,7 +52,7 @@ public final class NamingLookupRequestCodec implements Codec<NamingLookupRequest */ @Override public byte[] encode(final NamingLookupRequest obj) { - final List<CharSequence> ids = new ArrayList<>(); + final List<String> ids = new ArrayList<>(); for (final Identifier id : obj.getIdentifiers()) { ids.add(id.toString()); } http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/main/avro/class_hierarchy.avsc ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/main/avro/class_hierarchy.avsc b/lang/java/reef-tang/tang/src/main/avro/class_hierarchy.avsc new file mode 100644 index 0000000..058f847 --- /dev/null +++ b/lang/java/reef-tang/tang/src/main/avro/class_hierarchy.avsc @@ -0,0 +1,120 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +[ +{ + "namespace":"org.apache.reef.tang.formats.avro", + "type":"record", + "name":"AvroConstructorArg", + "fields":[ + {"name":"fullArgClassName", "type":"string"}, + {"name":"namedParameterName", "type":["null", "string"], "default":null}, + {"name":"isInjectionFuture", "type":"boolean"} + ] +}, +{ + "namespace":"org.apache.reef.tang.formats.avro", + "type":"record", + "name":"AvroConstructorDef", + "fields":[ + {"name":"fullArgClassName", "type":"string"}, + {"name":"constructorArg", "type":{"type":"array", "items":"AvroConstructorArg"}} + ] +}, +{ + "namespace":"org.apache.reef.tang.formats.avro", + "type":"record", + "name":"AvroNamedParameterNode", + "fields":[ + {"name":"simpleArgClassName", "type":"string"}, + {"name":"fullArgClassName", "type":"string"}, + {"name":"isSet", "type":"boolean"}, + {"name":"isList", "type":"boolean"}, + {"name":"documentation", "type":["null", "string"], "default":null}, + {"name":"shortName", "type":["null", "string"], "default":null}, + {"name":"instanceDefault", "type":{"type":"array","items":"string"}} + ] +}, +{ + "namespace":"org.apache.reef.tang.formats.avro", + "type":"record", + "name":"AvroClassNode", + "fields":[ + {"name":"isInjectionCandidate", "type":"boolean"}, + {"name":"isExternalConstructor", "type":"boolean"}, + {"name":"isUnit", "type":"boolean"}, + {"name":"injectableConstructors", "type":{"type":"array", "items":"AvroConstructorDef"}}, + {"name":"otherConstructors", "type":{"type":"array", "items":"AvroConstructorDef"}}, + {"name":"implFullNames", "type":{"type":"array", "items":"string"}}, + {"name":"defaultImplementation", "type":["null", "string"], "default":null} + ] +}, +/* + Intentionally left blank. Packages don't have any interesting + attributes except their names and children. +*/ +{ + "namespace":"org.apache.reef.tang.formats.avro", + "type":"record", + "name":"AvroPackageNode", + "fields":[] +}, +/* + Node is the abstract base type for all the data encoded in a class hierarchy. + It is represented as an (un)tagged union, so only one of the three optional + fields can be non-null. + */ +{ + "namespace":"org.apache.reef.tang.formats.avro", + "type":"record", + "name":"AvroNode", + "fields":[ + /* + The short name of this node (e.g., a class name without the enclosing + package, or a package name without the name of the enclosing package. + */ + {"name":"name", "type":"string"}, + /* + For some languages it can be difficult to map from a list of nodes to + the correct short name, so for now, the full name is (redundantly) + encoded here. In Java, the full name is a bunch of short names that + have been concatenated with "." and/or "$". + */ + {"name":"fullName", "type":"string"}, + + /* + * Exactly one of the next three fields must be defined. See below for + * their documentation. + */ + {"name":"classNode", "type":["null", "AvroClassNode"], "default":null}, + {"name":"namedParameterNode", "type":["null", "AvroNamedParameterNode"], "default":null}, + {"name":"packageNode", "type":["null", "AvroPackageNode"], "default":null}, + + /* + Class hierarchy nodes are arranged in a tree that mirrors the language + namespaces / packages that contain class names (e.g., Java packages, + C++ namespaces). + + A NamedParameterNode cannot have any children. A ClassNode can not have + any package nodes as children. PackageNodes cannot have PackageNodes as + children. + */ + {"name":"children", "type":{"type":"array","items":"AvroNode"}} + ] +} +] http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/ClassHierarchy.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/ClassHierarchy.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/ClassHierarchy.java index 4833717..9f89471 100644 --- a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/ClassHierarchy.java +++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/ClassHierarchy.java @@ -42,7 +42,6 @@ public interface ClassHierarchy { * @param fullName The full name of the class that will be looked up. * @return A non-null reference to a ClassNode or a NamedParameterNode. * @throws NameResolutionException If the class is not found. - * @throws ClassHierarchyException If the class does not pass Tang's static analysis. */ Node getNode(String fullName) throws NameResolutionException; http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroClassHierarchySerializer.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroClassHierarchySerializer.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroClassHierarchySerializer.java new file mode 100644 index 0000000..6c95498 --- /dev/null +++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroClassHierarchySerializer.java @@ -0,0 +1,255 @@ +package org.apache.reef.tang.formats; + +import org.apache.avro.file.DataFileReader; +import org.apache.avro.file.DataFileWriter; +import org.apache.avro.io.*; +import org.apache.avro.specific.SpecificDatumReader; +import org.apache.avro.specific.SpecificDatumWriter; +import org.apache.reef.tang.ClassHierarchy; +import org.apache.reef.tang.formats.avro.*; +import org.apache.reef.tang.implementation.java.AvroClassHierarchy; +import org.apache.reef.tang.types.*; + +import javax.inject.Inject; +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Serialize and Deserialize ClassHierarchy to and from AvroClassHierarchy. + * This class is stateless and is therefore safe to reuse. + */ +public class AvroClassHierarchySerializer implements ClassHierarchySerializer { + + /** + * The Charset used for the JSON encoding. + */ + private static final String JSON_CHARSET = "ISO-8859-1"; + + @Inject + public AvroClassHierarchySerializer() { + } + + /** + * Serialize the ClassHierarchy into the AvroNode. + * @param ch ClassHierarchy to serialize + */ + private static AvroNode toAvro(final ClassHierarchy ch) { + return newAvroNode(ch.getNamespace()); + } + + /** + * Deserialize the ClassHierarchy from the AvroNode. + * @param n AvroNode to deserialize + */ + private static ClassHierarchy fromAvro(final AvroNode n) { + return new AvroClassHierarchy(n); + } + + private static AvroNode newAvroNode(final Node n) { + final List<AvroNode> children = new ArrayList<>(); + for (final Node child : n.getChildren()) { + children.add(newAvroNode(child)); + } + if (n instanceof ClassNode) { + final ClassNode<?> cn = (ClassNode<?>) n; + final ConstructorDef<?>[] injectable = cn.getInjectableConstructors(); + final ConstructorDef<?>[] all = cn.getAllConstructors(); + final List<ConstructorDef<?>> others = new ArrayList<>(Arrays.asList(all)); + others.removeAll(Arrays.asList(injectable)); + + final List<AvroConstructorDef> injectableConstructors = new ArrayList<>(); + for (final ConstructorDef<?> inj : injectable) { + injectableConstructors.add(newConstructorDef(inj)); + } + final List<AvroConstructorDef> otherConstructors = new ArrayList<>(); + for (final ConstructorDef<?> other : others) { + otherConstructors.add(newConstructorDef(other)); + } + final List<String> implFullNames = new ArrayList<>(); + for (final ClassNode<?> impl : cn.getKnownImplementations()) { + implFullNames.add(impl.getFullName()); + } + return newClassNode(n.getName(), n.getFullName(), cn.isInjectionCandidate(), cn.isExternalConstructor(), + cn.isUnit(), injectableConstructors, otherConstructors, implFullNames, cn.getDefaultImplementation(), + children); + } else if (n instanceof NamedParameterNode) { + final NamedParameterNode<?> np = (NamedParameterNode<?>) n; + return newNamedParameterNode(np.getName(), np.getFullName(), np.getSimpleArgName(), np.getFullArgName(), + np.isSet(), np.isList(), np.getDocumentation(), np.getShortName(), + Arrays.asList(np.getDefaultInstanceAsStrings()), children); + } else if (n instanceof PackageNode) { + return newPackageNode(n.getName(), n.getFullName(), children); + } else { + throw new IllegalStateException("Encountered unknown type of Node: " + n); + } + } + + private static AvroNode newClassNode(final String name, + final String fullName, + final boolean isInjectionCandidate, + final boolean isExternalConstructor, + final boolean isUnit, + final List<AvroConstructorDef> injectableConstructors, + final List<AvroConstructorDef> otherConstructors, + final List<String> implFullNames, + final String defaultImplementation, + final List<AvroNode> children) { + return AvroNode.newBuilder() + .setName(name) + .setFullName(fullName) + .setClassNode(AvroClassNode.newBuilder() + .setIsInjectionCandidate(isInjectionCandidate) + .setIsExternalConstructor(isExternalConstructor) + .setIsUnit(isUnit) + .setInjectableConstructors(injectableConstructors) + .setOtherConstructors(otherConstructors) + .setImplFullNames(implFullNames) + .setDefaultImplementation(defaultImplementation) + .build()) + .setChildren(children).build(); + } + + private static AvroNode newNamedParameterNode(final String name, + final String fullName, + final String simpleArgClassName, + final String fullArgClassName, + final boolean isSet, + final boolean isList, + final String documentation, + final String shortName, + final List<String> instanceDefault, + final List<AvroNode> children) { + + return AvroNode.newBuilder() + .setName(name) + .setFullName(fullName) + .setNamedParameterNode(AvroNamedParameterNode.newBuilder() + .setSimpleArgClassName(simpleArgClassName) + .setFullArgClassName(fullArgClassName) + .setIsSet(isSet) + .setIsList(isList) + .setDocumentation(documentation) + .setShortName(shortName) + .setInstanceDefault(instanceDefault) + .build()) + .setChildren(children).build(); + } + + private static AvroNode newPackageNode(final String name, + final String fullName, + final List<AvroNode> children) { + return AvroNode.newBuilder() + .setPackageNode(AvroPackageNode.newBuilder().build()) + .setName(name).setFullName(fullName).setChildren(children).build(); + } + + private static AvroConstructorArg newConstructorArg(final String fullArgClassName, + final String namedParameterName, + final boolean isFuture) { + return AvroConstructorArg.newBuilder() + .setFullArgClassName(fullArgClassName) + .setIsInjectionFuture(isFuture) + .setNamedParameterName(namedParameterName).build(); + } + + private static AvroConstructorDef newConstructorDef(final ConstructorDef<?> def) { + final List<AvroConstructorArg> args = new ArrayList<>(); + for (final ConstructorArg arg : def.getArgs()) { + args.add(newConstructorArg(arg.getType(), arg.getNamedParameterName(), arg.isInjectionFuture())); + } + return AvroConstructorDef.newBuilder() + .setFullArgClassName(def.getClassName()) + .setConstructorArg(args).build(); + } + + @Override + public void toFile(final ClassHierarchy classHierarchy, final File file) throws IOException { + final AvroNode avroNode = toAvro(classHierarchy); + final DatumWriter<AvroNode> avroNodeWriter = new SpecificDatumWriter<>(AvroNode.class); + try (final DataFileWriter<AvroNode> dataFileWriter = new DataFileWriter<>(avroNodeWriter)) { + dataFileWriter.create(avroNode.getSchema(), file); + dataFileWriter.append(avroNode); + } + } + + @Override + public byte[] toByteArray(final ClassHierarchy classHierarchy) throws IOException { + final DatumWriter<AvroNode> requestWriter = new SpecificDatumWriter<>(AvroNode.class); + try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) { + final BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(out, null); + requestWriter.write(toAvro(classHierarchy), encoder); + encoder.flush(); + return out.toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public String toString(final ClassHierarchy classHierarchy) throws IOException { + final DatumWriter<AvroNode> classHierarchyWriter = new SpecificDatumWriter<>(AvroNode.class); + try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) { + final JsonEncoder encoder = EncoderFactory.get().jsonEncoder(AvroNode.SCHEMA$, out); + classHierarchyWriter.write(toAvro(classHierarchy), encoder); + encoder.flush(); + out.flush(); + return out.toString(JSON_CHARSET); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void toTextFile(ClassHierarchy classHierarchy, File file) throws IOException { + try (final Writer w = new FileWriter(file)) { + w.write(this.toString(classHierarchy)); + } + } + + @Override + public ClassHierarchy fromFile(final File file) throws IOException { + final AvroNode avroNode; + try (final DataFileReader<AvroNode> dataFileReader = + new DataFileReader<>(file, new SpecificDatumReader<>(AvroNode.class))) { + avroNode = dataFileReader.next(); + } + return fromAvro(avroNode); + } + + @Override + public ClassHierarchy fromByteArray(final byte[] theBytes) throws IOException { + try { + final BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(theBytes, null); + final SpecificDatumReader<AvroNode> reader = new SpecificDatumReader<>(AvroNode.class); + return fromAvro(reader.read(null, decoder)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public ClassHierarchy fromString(final String theString) throws IOException { + try { + final JsonDecoder decoder = DecoderFactory.get().jsonDecoder(AvroNode.getClassSchema(), theString); + final SpecificDatumReader<AvroNode> reader = new SpecificDatumReader<>(AvroNode.class); + return fromAvro(reader.read(null, decoder)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public ClassHierarchy fromTextFile(final File file) throws IOException { + final StringBuilder stringBuilder = new StringBuilder(); + try (final BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line = reader.readLine(); + while (line != null) { + stringBuilder.append(line); + line = reader.readLine(); + } + } + return fromString(stringBuilder.toString()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ClassHierarchySerializer.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ClassHierarchySerializer.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ClassHierarchySerializer.java new file mode 100644 index 0000000..4b7c357 --- /dev/null +++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ClassHierarchySerializer.java @@ -0,0 +1,79 @@ +package org.apache.reef.tang.formats; + +import org.apache.reef.tang.ClassHierarchy; +import org.apache.reef.tang.annotations.DefaultImplementation; +import org.apache.reef.tang.formats.avro.AvroNode; + +import java.io.*; + +/** + * A base interface for ClassHierarchy serializers. + */ +@DefaultImplementation(org.apache.reef.tang.formats.AvroClassHierarchySerializer.class) +public interface ClassHierarchySerializer { + /** + * Writes a ClassHierarchy into a file. + * + * @param classHierarchy the ClassHierarchy to store + * @param file the file to store the ClassHierarchy + * @throws IOException if there is an error in the process + */ + void toFile(final ClassHierarchy classHierarchy, final File file) throws IOException; + + /** + * Writes a ClassHierarchy into a text file. + * + * @param classHierarchy the ClassHierarchy to store + * @param file the text file to store the ClassHierarchy + * @throws IOException if there is an error in the process + */ + void toTextFile(final ClassHierarchy classHierarchy, final File file) throws IOException; + + /** + * Serializes a ClassHierarchy as a byte[]. + * + * @param classHierarchy the ClassHierarchy to store + * @throws IOException if there is an error in the process + */ + byte[] toByteArray(final ClassHierarchy classHierarchy) throws IOException; + + /** + * Serializes a ClassHierarchy as a String. + * + * @param classHierarchy the ClassHierarchy to store + * @throws IOException if there is an error in the process + */ + String toString(final ClassHierarchy classHierarchy) throws IOException; + + /** + * Loads a ClassHierarchy from a file created with toFile(). + * + * @param file the File to read from + * @throws IOException if the File can't be read or parsed + */ + ClassHierarchy fromFile(final File file) throws IOException; + + /** + * Loads a ClassHierarchy from a text file created with toTextFile(). + * + * @param file the File to read from + * @throws IOException if the File can't be read or parsed + */ + ClassHierarchy fromTextFile(final File file) throws IOException; + + /** + * Deserializes a ClassHierarchy from a byte[] created with toByteArray(). + * + * @param theBytes the byte[] to deserialize + * @throws IOException if the byte[] can't be read or parsed + */ + ClassHierarchy fromByteArray(final byte[] theBytes) throws IOException; + + /** + * Deserializes a ClassHierarchy from a String created with toString(). + * + * @param theString the String to deserialize + * @throws IOException if the String can't be read or parsed + */ + ClassHierarchy fromString(final String theString) throws IOException; +} http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/java/AvroClassHierarchy.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/java/AvroClassHierarchy.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/java/AvroClassHierarchy.java new file mode 100644 index 0000000..761fa5d --- /dev/null +++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/java/AvroClassHierarchy.java @@ -0,0 +1,200 @@ +package org.apache.reef.tang.implementation.java; + +import org.apache.reef.tang.ClassHierarchy; +import org.apache.reef.tang.annotations.NamedParameter; +import org.apache.reef.tang.exceptions.NameResolutionException; +import org.apache.reef.tang.formats.avro.*; +import org.apache.reef.tang.implementation.types.*; +import org.apache.reef.tang.types.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Implementation of ClassHierarchy for Avro + */ +public class AvroClassHierarchy implements ClassHierarchy { + private final PackageNode namespace; + private final HashMap<String, Node> lookupTable = new HashMap<>(); + + public AvroClassHierarchy(final AvroNode root) { + namespace = new PackageNodeImpl(); + if (root.getPackageNode() == null) { + throw new IllegalArgumentException("Expected a package node. Got: " + root); + } + + // Register all the classes. + for (final AvroNode child : root.getChildren()) { + parseSubHierarchy(namespace, child); + } + buildLookupTable(namespace); + + // Register the implementations + for (final AvroNode child : root.getChildren()) { + wireUpInheritanceRelationships(child); + } + } + + /** + * Build a table that maps the name to the corresponding Node recursively. + */ + private void buildLookupTable(final Node n) { + for(final Node child : n.getChildren()) { + lookupTable.put(child.getFullName(), child); + buildLookupTable(child); + } + } + + /** + * Parse the constructor definition. + */ + private static ConstructorDef<?> parseConstructorDef(final AvroConstructorDef def, final boolean isInjectable) { + final List<ConstructorArg> args = new ArrayList<>(); + for (final AvroConstructorArg arg : def.getConstructorArg()) { + args.add(new ConstructorArgImpl(arg.getFullArgClassName(), arg.getNamedParameterName(), arg.getIsInjectionFuture())); + } + return new ConstructorDefImpl<>(def.getFullArgClassName(), args.toArray(new ConstructorArg[0]), isInjectable); + } + + /** + * Register the classes recursively. + */ + private static void parseSubHierarchy(final Node parent, final AvroNode n) { + final Node parsed; + if (n.getPackageNode() != null) { + parsed = new PackageNodeImpl(parent, n.getName(), n.getFullName()); + } else if (n.getNamedParameterNode() != null) { + final AvroNamedParameterNode np = n.getNamedParameterNode(); + parsed = new NamedParameterNodeImpl<>(parent, n.getName(), n.getFullName(), + np.getFullArgClassName(), np.getSimpleArgClassName(), np.getIsSet(), np.getIsList(), + np.getDocumentation(), np.getShortName(), np.getInstanceDefault().toArray(new String[0])); + } else if (n.getClassNode() != null) { + final AvroClassNode cn = n.getClassNode(); + final List<ConstructorDef<?>> injectableConstructors = new ArrayList<>(); + final List<ConstructorDef<?>> allConstructors = new ArrayList<>(); + + for (final AvroConstructorDef injectable : cn.getInjectableConstructors()) { + final ConstructorDef<?> def = parseConstructorDef(injectable, true); + injectableConstructors.add(def); + allConstructors.add(def); + } + for (final AvroConstructorDef other : cn.getOtherConstructors()) { + final ConstructorDef<?> def = parseConstructorDef(other, false); + allConstructors.add(def); + } + @SuppressWarnings("unchecked") + final ConstructorDef<Object>[] dummy = new ConstructorDef[0]; + final String defaultImpl = cn.getDefaultImplementation() == null ? null : cn.getDefaultImplementation(); + parsed = new ClassNodeImpl<>(parent, n.getName(), n.getFullName(), cn.getIsUnit(), + cn.getIsInjectionCandidate(), cn.getIsExternalConstructor(), injectableConstructors.toArray(dummy), + allConstructors.toArray(dummy), defaultImpl); + } else { + throw new IllegalStateException("Bad avro node: got abstract node" + n); + } + + for (final AvroNode child : n.getChildren()) { + parseSubHierarchy(parsed, child); + } + } + + /** + * Register the implementation for the ClassNode recursively. + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private void wireUpInheritanceRelationships(final AvroNode n) { + if (n.getClassNode() != null) { + final AvroClassNode cn = n.getClassNode(); + final ClassNode iface; + try { + iface = (ClassNode) getNode(n.getFullName()); + } catch (NameResolutionException e) { + final String errorMessage = new StringBuilder() + .append("When reading avro node ").append(n.getFullName()) + .append(" does not exist. Full record is ").append(n).toString(); + throw new IllegalStateException(errorMessage, e); + } + for (final String impl : cn.getImplFullNames()) { + try { + iface.putImpl((ClassNode) getNode(impl)); + } catch (NameResolutionException e) { + final String errorMessage = new StringBuilder() + .append("When reading avro node ").append(n) + .append(" refers to non-existent implementation:").append(impl).toString(); + throw new IllegalStateException(errorMessage, e); + } catch (ClassCastException e) { + try { + final String errorMessage = new StringBuilder() + .append("When reading avro node ").append(n).append(" found implementation").append(getNode(impl)) + .append(" which is not a ClassNode!").toString(); + throw new IllegalStateException(errorMessage, e); + } catch (NameResolutionException e2) { + final String errorMessage = new StringBuilder() + .append("Got 'cant happen' exception when producing error message for ") + .append(e).toString(); + throw new IllegalStateException(errorMessage); + } + } + } + } + + for (final AvroNode child : n.getChildren()) { + wireUpInheritanceRelationships(child); + } + } + + @Override + public Node getNode(final String fullName) throws NameResolutionException { + final Node matchedNode = lookupTable.get(fullName); + if (matchedNode != null) { + return matchedNode; + } else { + throw new NameResolutionException(fullName, ""); + } + } + + @Override + public boolean isImplementation(final ClassNode<?> inter, final ClassNode<?> impl) { + return impl.isImplementationOf(inter); + } + + @Override + public ClassHierarchy merge(final ClassHierarchy ch) { + if (this == ch) { + return this; + } + if (!(ch instanceof AvroClassHierarchy)) { + throw new UnsupportedOperationException( + "Cannot merge with class hierarchies of type: " + ch.getClass().getName()); + } + + final AvroClassHierarchy ach = (AvroClassHierarchy) ch; + for (final String key : ach.lookupTable.keySet()) { + if (!this.lookupTable.containsKey(key)) { + this.lookupTable.put(key, ach.lookupTable.get(key)); + } + } + + for (final Node n : ch.getNamespace().getChildren()) { + if (!this.namespace.contains(n.getFullName())) { + if (n instanceof NamedParameter) { + final NamedParameterNode np = (NamedParameterNode) n; + new NamedParameterNodeImpl<>(this.namespace, np.getName(), np.getFullName(), np.getFullArgName(), + np.getSimpleArgName(), np.isSet(), np.isList(), np.getDocumentation(), np.getShortName(), + np.getDefaultInstanceAsStrings()); + } else if (n instanceof ClassNode) { + final ClassNode cn = (ClassNode) n; + new ClassNodeImpl<>(namespace, cn.getName(), cn.getFullName(), cn.isUnit(), cn.isInjectionCandidate(), + cn.isExternalConstructor(), cn.getInjectableConstructors(), cn.getAllConstructors(), + cn.getDefaultImplementation()); + } + } + } + return this; + } + + @Override + public Node getNamespace() { + return namespace; + } +} http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/protobuf/ProtocolBufferClassHierarchy.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/protobuf/ProtocolBufferClassHierarchy.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/protobuf/ProtocolBufferClassHierarchy.java index 29b4939..8429c4a 100644 --- a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/protobuf/ProtocolBufferClassHierarchy.java +++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/protobuf/ProtocolBufferClassHierarchy.java @@ -31,6 +31,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; +@Deprecated public class ProtocolBufferClassHierarchy implements ClassHierarchy { private static final String regex = "[\\.\\$\\+]"; http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/util/ValidateConfiguration.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/util/ValidateConfiguration.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/util/ValidateConfiguration.java index 82c929c..31f4b96 100644 --- a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/util/ValidateConfiguration.java +++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/util/ValidateConfiguration.java @@ -36,6 +36,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +// TODO Clean up the code which are deprecated and commented out. public class ValidateConfiguration { private final String target; private final File ch; @@ -85,6 +86,7 @@ public class ValidateConfiguration { final Tang t = Tang.Factory.getTang(); + // TODO Use the AvroClassHierarchySerializer final ClassHierarchyProto.Node root; try (final InputStream chin = new FileInputStream(this.ch)) { root = ClassHierarchyProto.Node.parseFrom(chin); http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/ClassHierarchyDeserializationTest.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/ClassHierarchyDeserializationTest.java b/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/ClassHierarchyDeserializationTest.java index a7e1469..f0aebaa 100644 --- a/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/ClassHierarchyDeserializationTest.java +++ b/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/ClassHierarchyDeserializationTest.java @@ -18,9 +18,10 @@ */ package org.apache.reef.tang; -import org.apache.reef.tang.exceptions.BindException; import org.apache.reef.tang.exceptions.NameResolutionException; +import org.apache.reef.tang.formats.AvroClassHierarchySerializer; import org.apache.reef.tang.formats.AvroConfigurationSerializer; +import org.apache.reef.tang.formats.ClassHierarchySerializer; import org.apache.reef.tang.formats.ConfigurationSerializer; import org.apache.reef.tang.implementation.protobuf.ProtocolBufferClassHierarchy; import org.apache.reef.tang.proto.ClassHierarchyProto; @@ -35,16 +36,21 @@ import java.util.Set; /** * Test case for class hierarchy deserialization. + * TODO The files should be created and deserialized by the AvroClassHierarchySerializer */ public class ClassHierarchyDeserializationTest { + private final ConfigurationSerializer configurationSerializer = new AvroConfigurationSerializer(); + private final ClassHierarchySerializer classHierarchySerializer = new AvroClassHierarchySerializer(); /** * generate task.bin from running .Net ClassHierarchyBuilder.exe */ @Test public void testDeserializationForTasks() { + // TODO The file should be written by Avro try (final InputStream chin = Thread.currentThread().getContextClassLoader() .getResourceAsStream("Task.bin")) { + // TODO Use AvroClassHierarchySerializer instead final ClassHierarchyProto.Node root = ClassHierarchyProto.Node.parseFrom(chin); final ClassHierarchy ch = new ProtocolBufferClassHierarchy(root); Node n1 = ch.getNode("Org.Apache.REEF.Examples.Tasks.StreamingTasks.StreamTask1, Org.Apache.REEF.Examples.Tasks, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); @@ -75,8 +81,10 @@ public class ClassHierarchyDeserializationTest { final ConfigurationBuilder taskConfigurationBuilder; final ConfigurationBuilder eventConfigurationBuilder; + // TODO The file should be written by Avro try (final InputStream chin = Thread.currentThread().getContextClassLoader() .getResourceAsStream("Task.bin")) { + // TODO Use AvroClassHierarchySerializer instead final ClassHierarchyProto.Node root = ClassHierarchyProto.Node.parseFrom(chin); final ClassHierarchy ch = new ProtocolBufferClassHierarchy(root); taskConfigurationBuilder = Tang.Factory.getTang().newConfigurationBuilder(ch); @@ -85,8 +93,10 @@ public class ClassHierarchyDeserializationTest { throw new RuntimeException(message, e); } + // TODO The file should be written by Avro try (final InputStream chin = Thread.currentThread().getContextClassLoader() .getResourceAsStream("Event.bin")) { + // TODO Use AvroClassHierarchySerializer instead final ClassHierarchyProto.Node root = ClassHierarchyProto.Node.parseFrom(chin); final ClassHierarchy ch = new ProtocolBufferClassHierarchy(root); eventConfigurationBuilder = Tang.Factory.getTang().newConfigurationBuilder(ch); @@ -103,8 +113,10 @@ public class ClassHierarchyDeserializationTest { */ @Test public void testDeserializationForEvent() { + // TODO The file should be written by Avro try (final InputStream chin = Thread.currentThread().getContextClassLoader() .getResourceAsStream("Event.bin")) { + // TODO Use AvroClassHierarchySerializer instead final ClassHierarchyProto.Node root = ClassHierarchyProto.Node.parseFrom(chin); final ClassHierarchy ch = new ProtocolBufferClassHierarchy(root); final ConfigurationBuilder taskConfigurationBuilder = Tang.Factory.getTang() @@ -120,15 +132,14 @@ public class ClassHierarchyDeserializationTest { public void testBindSetEntryWithSetOfT() throws IOException { final ClassHierarchy ns1 = Tang.Factory.getTang().getDefaultClassHierarchy(); ns1.getNode(SetOfClasses.class.getName()); - final ClassHierarchy ns2 = new ProtocolBufferClassHierarchy(ProtocolBufferClassHierarchy.serialize(ns1)); + final ClassHierarchy ns2 = classHierarchySerializer.fromString(classHierarchySerializer.toString(ns1)); final ConfigurationBuilder cb = Tang.Factory.getTang().newConfigurationBuilder(ns2); final NamedParameterNode<Set<Number>> n2 = (NamedParameterNode<Set<Number>>) ns1.getNode(SetOfClasses.class.getName()); final Node fn = ns1.getNode(Float.class.getName()); cb.bindSetEntry(n2, fn); - final ConfigurationSerializer serializer = new AvroConfigurationSerializer(); - final Configuration c = serializer.fromString(serializer.toString(cb.build()), ns2); + final Configuration c = configurationSerializer.fromString(configurationSerializer.toString(cb.build()), ns2); } @Test @@ -136,7 +147,7 @@ public class ClassHierarchyDeserializationTest { public void testBindSetEntryWithSetOfString() throws IOException { final ClassHierarchy ns1 = Tang.Factory.getTang().getDefaultClassHierarchy(); ns1.getNode(SetOfStrings.class.getName()); - final ClassHierarchy ns2 = new ProtocolBufferClassHierarchy(ProtocolBufferClassHierarchy.serialize(ns1)); + final ClassHierarchy ns2 = classHierarchySerializer.fromString(classHierarchySerializer.toString(ns1)); final ConfigurationBuilder cb = Tang.Factory.getTang().newConfigurationBuilder(ns2); cb.bindSetEntry(SetOfStrings.class.getName(), "four"); cb.bindSetEntry(SetOfStrings.class.getName(), "five"); @@ -144,7 +155,6 @@ public class ClassHierarchyDeserializationTest { final NamedParameterNode<Set<String>> n2 = (NamedParameterNode<Set<String>>) ns1.getNode(SetOfStrings.class.getName()); cb.bindSetEntry(n2, "six"); - final ConfigurationSerializer serializer = new AvroConfigurationSerializer(); - final Configuration c = serializer.fromString(serializer.toString(cb.build()), ns2); + final Configuration c = configurationSerializer.fromString(configurationSerializer.toString(cb.build()), ns2); } } http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/formats/TestClassHierarchyRoundTrip.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/formats/TestClassHierarchyRoundTrip.java b/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/formats/TestClassHierarchyRoundTrip.java new file mode 100644 index 0000000..4029f6c --- /dev/null +++ b/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/formats/TestClassHierarchyRoundTrip.java @@ -0,0 +1,551 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.reef.tang.formats; + +import org.apache.reef.tang.Tang; +import org.apache.reef.tang.exceptions.InjectionException; +import org.apache.reef.tang.exceptions.NameResolutionException; +import org.apache.reef.tang.implementation.TangImpl; +import org.apache.reef.tang.implementation.TestClassHierarchy; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +public class TestClassHierarchyRoundTrip extends TestClassHierarchy { + final ClassHierarchySerializer serializer = new AvroClassHierarchySerializer(); + + // The default ClassHierarchy + private void setup0() { + TangImpl.reset(); + ns = Tang.Factory.getTang().getDefaultClassHierarchy(); + } + + // Serializes ClassHierarchy to file + private void setup1() { + TangImpl.reset(); + try { + final File file = java.io.File.createTempFile("TangTest", "avroch"); + serializer.toFile(ns, file); + ns = serializer.fromFile(file); + file.delete(); + } catch (IOException e) { + Assert.fail(String.format("IOException when serialize/deserialize the ClassHierarchy", e)); + } + } + + // Serializes ClassHierarchy to TextFile + private void setup2() { + TangImpl.reset(); + try { + final File textFile = java.io.File.createTempFile("TangTest", "avroch"); + serializer.toTextFile(ns, textFile); + ns = serializer.fromTextFile(textFile); + textFile.delete(); + } catch (IOException e) { + Assert.fail(String.format("IOException when serialize/deserialize the ClassHierarchy", e)); + } + } + + // Serializes ClassHierarchy to byte[] + private void setup3() { + TangImpl.reset(); + try { + ns = serializer.fromByteArray(serializer.toByteArray(ns)); + } catch (IOException e) { + Assert.fail(String.format("IOException when serialize/deserialize the ClassHierarchy", e)); + } + } + + // Serializes ClassHierarchy to String + private void setup4() { + TangImpl.reset(); + try { + ns = serializer.fromString(serializer.toString(ns)); + } catch (IOException e) { + Assert.fail(String.format("IOException when serialize/deserialize the ClassHierarchy", e)); + } + } + + @Test + @Override + public void testJavaString() throws NameResolutionException { + setup0(); + super.testJavaString(); + setup1(); + super.testJavaString(); + setup2(); + super.testJavaString(); + setup3(); + super.testJavaString(); + setup4(); + super.testJavaString(); + } + + @Test + @Override + public void testSimpleConstructors() throws NameResolutionException { + setup0(); + super.testSimpleConstructors(); + setup1(); + super.testSimpleConstructors(); + setup2(); + super.testSimpleConstructors(); + setup3(); + super.testSimpleConstructors(); + setup4(); + super.testSimpleConstructors(); + } + + @Test + @Override + public void testNamedParameterConstructors() throws NameResolutionException { + setup0(); + super.testNamedParameterConstructors(); + setup1(); + super.testNamedParameterConstructors(); + setup2(); + super.testNamedParameterConstructors(); + setup3(); + super.testNamedParameterConstructors(); + setup4(); + super.testNamedParameterConstructors(); + } + + @Test + @Override + public void testArray() throws NameResolutionException { + setup0(); + super.testArray(); + setup1(); + super.testArray(); + setup2(); + super.testArray(); + setup3(); + super.testArray(); + setup4(); + super.testArray(); + } + + @Test + @Override + public void testRepeatConstructorArg() throws NameResolutionException { + setup0(); + super.testRepeatConstructorArg(); + setup1(); + super.testRepeatConstructorArg(); + setup2(); + super.testRepeatConstructorArg(); + setup3(); + super.testRepeatConstructorArg(); + setup4(); + super.testRepeatConstructorArg(); + } + + @Test + @Override + public void testRepeatConstructorArgClasses() throws NameResolutionException { + setup0(); + super.testRepeatConstructorArgClasses(); + setup1(); + super.testRepeatConstructorArgClasses(); + setup2(); + super.testRepeatConstructorArgClasses(); + setup3(); + super.testRepeatConstructorArgClasses(); + setup4(); + super.testRepeatConstructorArgClasses(); + } + + @Test + @Override + public void testLeafRepeatedConstructorArgClasses() throws NameResolutionException { + setup0(); + super.testLeafRepeatedConstructorArgClasses(); + setup1(); + super.testLeafRepeatedConstructorArgClasses(); + setup2(); + super.testLeafRepeatedConstructorArgClasses(); + setup3(); + super.testLeafRepeatedConstructorArgClasses(); + setup4(); + super.testLeafRepeatedConstructorArgClasses(); + } + + @Test + @Override + public void testNamedRepeatConstructorArgClasses() throws NameResolutionException { + setup0(); + super.testNamedRepeatConstructorArgClasses(); + setup1(); + super.testNamedRepeatConstructorArgClasses(); + setup2(); + super.testNamedRepeatConstructorArgClasses(); + setup3(); + super.testNamedRepeatConstructorArgClasses(); + setup4(); + super.testNamedRepeatConstructorArgClasses(); + } + + @Test + @Override + public void testResolveDependencies() throws NameResolutionException { + setup0(); + super.testResolveDependencies(); + setup1(); + super.testResolveDependencies(); + setup2(); + super.testResolveDependencies(); + setup3(); + super.testResolveDependencies(); + setup4(); + super.testResolveDependencies(); + } + + @Test + @Override + public void testDocumentedLocalNamedParameter() throws NameResolutionException { + setup0(); + super.testDocumentedLocalNamedParameter(); + setup1(); + super.testDocumentedLocalNamedParameter(); + setup2(); + super.testDocumentedLocalNamedParameter(); + setup3(); + super.testDocumentedLocalNamedParameter(); + setup4(); + super.testDocumentedLocalNamedParameter(); + } + + @Test + @Override + public void testNamedParameterTypeMismatch() throws NameResolutionException { + setup0(); + super.testNamedParameterTypeMismatch(); + setup1(); + super.testNamedParameterTypeMismatch(); + setup2(); + super.testNamedParameterTypeMismatch(); + setup3(); + super.testNamedParameterTypeMismatch(); + setup4(); + super.testNamedParameterTypeMismatch(); + } + + @Test + @Override + public void testUnannotatedName() throws NameResolutionException { + setup0(); + super.testUnannotatedName(); + setup1(); + super.testUnannotatedName(); + setup2(); + super.testUnannotatedName(); + setup3(); + super.testUnannotatedName(); + setup4(); + super.testUnannotatedName(); + } + + @Test + @Override + public void testAnnotatedNotName() throws NameResolutionException { + setup0(); + super.testAnnotatedNotName(); + setup1(); + super.testAnnotatedNotName(); + setup2(); + super.testAnnotatedNotName(); + setup3(); + super.testAnnotatedNotName(); + setup4(); + super.testAnnotatedNotName(); + } + + @Test + @Override + public void testGenericTorture1() throws NameResolutionException { + setup0(); + super.testGenericTorture1(); + setup1(); + super.testGenericTorture1(); + setup2(); + super.testGenericTorture1(); + setup3(); + super.testGenericTorture1(); + setup4(); + super.testGenericTorture1(); + } + + @Test + @Override + public void testGenericTorture3() throws NameResolutionException { + setup0(); + super.testGenericTorture3(); + setup1(); + super.testGenericTorture3(); + setup2(); + super.testGenericTorture3(); + setup3(); + super.testGenericTorture3(); + setup4(); + super.testGenericTorture3(); + } + + @Test + @Override + public void testGenericTorture4() throws NameResolutionException { + setup0(); + super.testGenericTorture4(); + setup1(); + super.testGenericTorture4(); + setup2(); + super.testGenericTorture4(); + setup3(); + super.testGenericTorture4(); + setup4(); + super.testGenericTorture4(); + } + + @Test + @Override + public void testGenericTorture5() throws NameResolutionException { + setup0(); + super.testGenericTorture5(); + setup1(); + super.testGenericTorture5(); + setup2(); + super.testGenericTorture5(); + setup3(); + super.testGenericTorture5(); + setup4(); + super.testGenericTorture5(); + } + + @Test + @Override + public void testGenericTorture6() throws NameResolutionException { + setup0(); + super.testGenericTorture6(); + setup1(); + super.testGenericTorture6(); + setup2(); + super.testGenericTorture6(); + setup3(); + super.testGenericTorture6(); + setup4(); + super.testGenericTorture6(); + } + + @Test + @Override + public void testGenericTorture7() throws NameResolutionException { + setup0(); + super.testGenericTorture7(); + setup1(); + super.testGenericTorture7(); + setup2(); + super.testGenericTorture7(); + setup3(); + super.testGenericTorture7(); + setup4(); + super.testGenericTorture7(); + } + + @Test + @Override + public void testGenericTorture8() throws NameResolutionException { + setup0(); + super.testGenericTorture8(); + setup1(); + super.testGenericTorture8(); + setup2(); + super.testGenericTorture8(); + setup3(); + super.testGenericTorture8(); + setup4(); + super.testGenericTorture8(); + } + + @Test + @Override + public void testGenericTorture9() throws NameResolutionException { + setup0(); + super.testGenericTorture9(); + setup1(); + super.testGenericTorture9(); + setup2(); + super.testGenericTorture9(); + setup3(); + super.testGenericTorture9(); + setup4(); + super.testGenericTorture9(); + } + + @Test + @Override + public void testGenericTorture10() throws NameResolutionException { + setup0(); + super.testGenericTorture10(); + setup1(); + super.testGenericTorture10(); + setup2(); + super.testGenericTorture10(); + setup3(); + super.testGenericTorture10(); + setup4(); + super.testGenericTorture10(); + } + + @Test + @Override + public void testGenericTorture11() throws NameResolutionException { + setup0(); + super.testGenericTorture11(); + setup1(); + super.testGenericTorture11(); + setup2(); + super.testGenericTorture11(); + setup3(); + super.testGenericTorture11(); + setup4(); + super.testGenericTorture11(); + } + + @Test + @Override + public void testGenericTorture12() throws NameResolutionException { + setup0(); + super.testGenericTorture12(); + setup1(); + super.testGenericTorture12(); + setup2(); + super.testGenericTorture12(); + setup3(); + super.testGenericTorture12(); + setup4(); + super.testGenericTorture12(); + } + + @Test + @Override + public void testInjectNonStaticLocalArgClass() throws NameResolutionException { + setup0(); + super.testInjectNonStaticLocalArgClass(); + setup1(); + super.testInjectNonStaticLocalArgClass(); + setup2(); + super.testInjectNonStaticLocalArgClass(); + setup3(); + super.testInjectNonStaticLocalArgClass(); + setup4(); + super.testInjectNonStaticLocalArgClass(); + } + + @Test + @Override + public void testOKShortNames() throws NameResolutionException { + setup0(); + super.testOKShortNames(); + setup1(); + super.testOKShortNames(); + setup2(); + super.testOKShortNames(); + setup3(); + super.testOKShortNames(); + setup4(); + super.testOKShortNames(); + } + + @Test + @Override + public void testRoundTripInnerClassNames() throws NameResolutionException, ClassNotFoundException { + setup0(); + super.testRoundTripInnerClassNames(); + setup1(); + super.testRoundTripInnerClassNames(); + setup2(); + super.testRoundTripInnerClassNames(); + setup3(); + super.testRoundTripInnerClassNames(); + setup4(); + super.testRoundTripInnerClassNames(); + } + + @Test + @Override + public void testUnitIsInjectable() throws NameResolutionException, InjectionException { + setup0(); + super.testUnitIsInjectable(); + setup1(); + super.testUnitIsInjectable(); + setup2(); + super.testUnitIsInjectable(); + setup3(); + super.testUnitIsInjectable(); + setup4(); + super.testUnitIsInjectable(); + } + + @Test + @Override + public void testBadUnitDecl() throws NameResolutionException { + setup0(); + super.testBadUnitDecl(); + setup1(); + super.testBadUnitDecl(); + setup2(); + super.testBadUnitDecl(); + setup3(); + super.testBadUnitDecl(); + setup4(); + super.testBadUnitDecl(); + } + + @Test + @Override + public void nameCantBindWrongSubclassAsDefault() throws NameResolutionException { + setup0(); + super.nameCantBindWrongSubclassAsDefault(); + setup1(); + super.nameCantBindWrongSubclassAsDefault(); + setup2(); + super.nameCantBindWrongSubclassAsDefault(); + setup3(); + super.nameCantBindWrongSubclassAsDefault(); + setup4(); + super.nameCantBindWrongSubclassAsDefault(); + } + + @Test + @Override + public void ifaceCantBindWrongImplAsDefault() throws NameResolutionException { + setup0(); + super.ifaceCantBindWrongImplAsDefault(); + setup1(); + super.ifaceCantBindWrongImplAsDefault(); + setup2(); + super.ifaceCantBindWrongImplAsDefault(); + setup3(); + super.ifaceCantBindWrongImplAsDefault(); + setup4(); + super.ifaceCantBindWrongImplAsDefault(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/implementation/protobuf/TestClassHierarchyRoundTrip.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/implementation/protobuf/TestClassHierarchyRoundTrip.java b/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/implementation/protobuf/TestClassHierarchyRoundTrip.java deleted file mode 100644 index d50ded5..0000000 --- a/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/implementation/protobuf/TestClassHierarchyRoundTrip.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.reef.tang.implementation.protobuf; - -import org.apache.reef.tang.Tang; -import org.apache.reef.tang.exceptions.InjectionException; -import org.apache.reef.tang.exceptions.NameResolutionException; -import org.apache.reef.tang.implementation.TangImpl; -import org.apache.reef.tang.implementation.TestClassHierarchy; -import org.junit.Assert; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -public class TestClassHierarchyRoundTrip extends TestClassHierarchy { - - private void setup1() { - TangImpl.reset(); - ns = Tang.Factory.getTang().getDefaultClassHierarchy(); - } - - private void setup2() { - TangImpl.reset(); - ns = new ProtocolBufferClassHierarchy(ProtocolBufferClassHierarchy.serialize(ns)); - } - - private void setup3() { - TangImpl.reset(); - try { - final File file = java.io.File.createTempFile("testProto", "bin"); - ProtocolBufferClassHierarchy.serialize(file, ns); - ns = ProtocolBufferClassHierarchy.deserialize(file); - file.delete(); - } catch (IOException e) { - Assert.fail(String.format("IOException when serialize/deserialize proto buffer file ", e)); - } - } - - @Test - @Override - public void testJavaString() throws NameResolutionException { - setup1(); - super.testJavaString(); - setup2(); - super.testJavaString(); - setup3(); - super.testJavaString(); - } - - @Test - @Override - public void testSimpleConstructors() throws NameResolutionException { - setup1(); - super.testSimpleConstructors(); - setup2(); - super.testSimpleConstructors(); - setup3(); - super.testSimpleConstructors(); - } - - @Test - @Override - public void testNamedParameterConstructors() throws NameResolutionException { - setup1(); - super.testNamedParameterConstructors(); - setup2(); - super.testNamedParameterConstructors(); - setup3(); - super.testNamedParameterConstructors(); - } - - @Test - @Override - public void testArray() throws NameResolutionException { - setup1(); - super.testArray(); - setup2(); - super.testArray(); - setup3(); - super.testArray(); - } - - @Test - @Override - public void testRepeatConstructorArg() throws NameResolutionException { - setup1(); - super.testRepeatConstructorArg(); - setup2(); - super.testRepeatConstructorArg(); - setup3(); - super.testRepeatConstructorArg(); - } - - @Test - @Override - public void testRepeatConstructorArgClasses() throws NameResolutionException { - setup1(); - super.testRepeatConstructorArgClasses(); - setup2(); - super.testRepeatConstructorArgClasses(); - setup3(); - super.testRepeatConstructorArgClasses(); - } - - @Test - @Override - public void testLeafRepeatedConstructorArgClasses() throws NameResolutionException { - setup1(); - super.testLeafRepeatedConstructorArgClasses(); - setup2(); - super.testLeafRepeatedConstructorArgClasses(); - setup3(); - super.testLeafRepeatedConstructorArgClasses(); - } - - @Test - @Override - public void testNamedRepeatConstructorArgClasses() throws NameResolutionException { - setup1(); - super.testNamedRepeatConstructorArgClasses(); - setup2(); - super.testNamedRepeatConstructorArgClasses(); - setup3(); - super.testNamedRepeatConstructorArgClasses(); - } - - @Test - @Override - public void testResolveDependencies() throws NameResolutionException { - setup1(); - super.testResolveDependencies(); - setup2(); - super.testResolveDependencies(); - setup3(); - super.testResolveDependencies(); - } - - @Test - @Override - public void testDocumentedLocalNamedParameter() throws NameResolutionException { - setup1(); - super.testDocumentedLocalNamedParameter(); - setup2(); - super.testDocumentedLocalNamedParameter(); - setup3(); - super.testDocumentedLocalNamedParameter(); - } - - @Test - @Override - public void testNamedParameterTypeMismatch() throws NameResolutionException { - setup1(); - super.testNamedParameterTypeMismatch(); - setup2(); - super.testNamedParameterTypeMismatch(); - setup3(); - super.testNamedParameterTypeMismatch(); - } - - @Test - @Override - public void testUnannotatedName() throws NameResolutionException { - setup1(); - super.testUnannotatedName(); - setup2(); - super.testUnannotatedName(); - setup3(); - super.testUnannotatedName(); - } - - @Test - @Override - public void testAnnotatedNotName() throws NameResolutionException { - setup1(); - super.testAnnotatedNotName(); - setup2(); - super.testAnnotatedNotName(); - setup3(); - super.testAnnotatedNotName(); - } - - @Test - @Override - public void testGenericTorture1() throws NameResolutionException { - setup1(); - super.testGenericTorture1(); - setup2(); - super.testGenericTorture1(); - setup3(); - super.testGenericTorture1(); - } - - @Test - @Override - public void testGenericTorture2() throws NameResolutionException { - setup1(); - super.testGenericTorture2(); - setup2(); - super.testGenericTorture2(); - setup3(); - super.testGenericTorture2(); - } - - @Test - @Override - public void testGenericTorture3() throws NameResolutionException { - setup1(); - super.testGenericTorture3(); - setup2(); - super.testGenericTorture3(); - setup3(); - super.testGenericTorture3(); - } - - @Test - @Override - public void testGenericTorture4() throws NameResolutionException { - setup1(); - super.testGenericTorture4(); - setup2(); - super.testGenericTorture4(); - setup3(); - super.testGenericTorture4(); - } - - @Test - @Override - public void testGenericTorture5() throws NameResolutionException { - setup1(); - super.testGenericTorture5(); - setup2(); - super.testGenericTorture5(); - setup3(); - super.testGenericTorture5(); - } - - @Test - @Override - public void testGenericTorture6() throws NameResolutionException { - setup1(); - super.testGenericTorture6(); - setup2(); - super.testGenericTorture6(); - setup3(); - super.testGenericTorture6(); - } - - @Test - @Override - public void testGenericTorture7() throws NameResolutionException { - setup1(); - super.testGenericTorture7(); - setup2(); - super.testGenericTorture7(); - setup3(); - super.testGenericTorture7(); - } - - @Test - @Override - public void testGenericTorture8() throws NameResolutionException { - setup1(); - super.testGenericTorture8(); - setup2(); - super.testGenericTorture8(); - setup3(); - super.testGenericTorture8(); - } - - @Test - @Override - public void testGenericTorture9() throws NameResolutionException { - setup1(); - super.testGenericTorture9(); - setup2(); - super.testGenericTorture9(); - setup3(); - super.testGenericTorture9(); - } - - @Test - @Override - public void testGenericTorture10() throws NameResolutionException { - setup1(); - super.testGenericTorture10(); - setup2(); - super.testGenericTorture10(); - } - - @Test - @Override - public void testGenericTorture11() throws NameResolutionException { - setup1(); - super.testGenericTorture11(); - setup2(); - super.testGenericTorture11(); - } - - @Test - @Override - public void testGenericTorture12() throws NameResolutionException { - setup1(); - super.testGenericTorture12(); - setup2(); - super.testGenericTorture12(); - } - - @Test - @Override - public void testInjectNonStaticLocalArgClass() throws NameResolutionException { - setup1(); - super.testInjectNonStaticLocalArgClass(); - setup2(); - super.testInjectNonStaticLocalArgClass(); - setup3(); - super.testInjectNonStaticLocalArgClass(); - } - - @Test - @Override - public void testOKShortNames() throws NameResolutionException { - setup1(); - super.testOKShortNames(); - setup2(); - super.testOKShortNames(); - setup3(); - super.testOKShortNames(); - } - - @Test - @Override - public void testRoundTripInnerClassNames() throws NameResolutionException, ClassNotFoundException { - setup1(); - super.testRoundTripInnerClassNames(); - setup2(); - super.testRoundTripInnerClassNames(); - setup3(); - super.testRoundTripInnerClassNames(); - } - - @Test - @Override - public void testUnitIsInjectable() throws NameResolutionException, InjectionException { - setup1(); - super.testUnitIsInjectable(); - setup2(); - super.testUnitIsInjectable(); - setup3(); - super.testUnitIsInjectable(); - } - - @Test - @Override - public void testBadUnitDecl() throws NameResolutionException { - setup1(); - super.testBadUnitDecl(); - setup2(); - super.testBadUnitDecl(); - setup3(); - super.testBadUnitDecl(); - } - - @Test - @Override - public void nameCantBindWrongSubclassAsDefault() throws NameResolutionException { - setup1(); - super.nameCantBindWrongSubclassAsDefault(); - setup2(); - super.nameCantBindWrongSubclassAsDefault(); - setup3(); - super.nameCantBindWrongSubclassAsDefault(); - } - - @Test - @Override - public void ifaceCantBindWrongImplAsDefault() throws NameResolutionException { - setup1(); - super.ifaceCantBindWrongImplAsDefault(); - setup2(); - super.ifaceCantBindWrongImplAsDefault(); - setup3(); - super.ifaceCantBindWrongImplAsDefault(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/test/RoundTripTest.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/test/RoundTripTest.java b/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/test/RoundTripTest.java index 2dd34a6..7000568 100644 --- a/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/test/RoundTripTest.java +++ b/lang/java/reef-tang/tang/src/test/java/org/apache/reef/tang/test/RoundTripTest.java @@ -21,7 +21,8 @@ package org.apache.reef.tang.test; import org.apache.reef.tang.ClassHierarchy; import org.apache.reef.tang.Configuration; import org.apache.reef.tang.Tang; -import org.apache.reef.tang.implementation.protobuf.ProtocolBufferClassHierarchy; +import org.apache.reef.tang.formats.AvroClassHierarchySerializer; +import org.apache.reef.tang.formats.ClassHierarchySerializer; import org.junit.Assert; import org.junit.Test; @@ -48,7 +49,8 @@ public abstract class RoundTripTest { public void testRoundTripWithClassHierarchy() throws Exception { // TODO: use 'getConfiguration' instead of 'getConfigurationWithoutList' after #192 is fixed final Configuration confBefore = ObjectTreeTest.getConfigurationWithoutList(); - final ClassHierarchy c = new ProtocolBufferClassHierarchy(ProtocolBufferClassHierarchy.serialize(confBefore.getClassHierarchy())); + final ClassHierarchySerializer chSerializer = new AvroClassHierarchySerializer(); + final ClassHierarchy c = chSerializer.fromString(chSerializer.toString(confBefore.getClassHierarchy())); final Configuration confAfter = roundTrip(confBefore, c); Assert.assertEquals(confBefore.getNamedParameters().size(), confAfter.getNamedParameters().size()); //For now, we cannot use ProtocolBufferClassHierarchy to do injection http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/cb901a66/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 60f50e8..1cbdde3 100644 --- a/pom.xml +++ b/pom.xml @@ -211,6 +211,9 @@ under the License. <groupId>org.apache.avro</groupId> <artifactId>avro-maven-plugin</artifactId> <version>${avro.version}</version> + <configuration> + <stringType>String</stringType> + </configuration> <executions> <execution> <phase>generate-sources</phase>
