Define AvroClassHierarchy which implements ClassHierarchy interface
Project: http://git-wip-us.apache.org/repos/asf/incubator-reef/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-reef/commit/1d370951 Tree: http://git-wip-us.apache.org/repos/asf/incubator-reef/tree/1d370951 Diff: http://git-wip-us.apache.org/repos/asf/incubator-reef/diff/1d370951 Branch: refs/heads/REEF-395 Commit: 1d37095112b3069ea180988630ed67c66101bdac Parents: beb1aef Author: Yunseong Lee <[email protected]> Authored: Sat Jun 20 02:16:13 2015 +0900 Committer: Yunseong Lee <[email protected]> Committed: Sat Jun 20 02:16:13 2015 +0900 ---------------------------------------------------------------------- .../implementation/java/AvroClassHierarchy.java | 188 +++++++++++++++++++ 1 file changed, 188 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1d370951/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..96ab16c --- /dev/null +++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/implementation/java/AvroClassHierarchy.java @@ -0,0 +1,188 @@ +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 + */ +// TODO Should it be a ClassHierarchy? +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); + // Now, register the implementations + for (final AvroNode child : root.getChildren()) { + wireUpInheritanceRelationships(child); + } + } + + private void buildLookupTable(final Node n) { + for(final Node child : n.getChildren()) { + lookupTable.put(child.getFullName(), child); + buildLookupTable(child); + } + } + + private static ConstructorDef<?> parseConstructorDef(final AvroConstructorDef def, final boolean isInjectable) { + final List<ConstructorArg> args = new ArrayList<>(); + for (final AvroConstructorArg arg : def.getConstructorArg()) { + final String namedParameterName = arg.getNamedParameterName() == null ? null : arg.getNamedParameterName(); + args.add(new ConstructorArgImpl(arg.getFullArgClassName(), namedParameterName, + arg.getIsInjectionFuture())); + } + return new ConstructorDefImpl<>(def.getFullArgClassName(), args.toArray(new ConstructorArg[0]), + isInjectable); + } + + private static void parseSubHierarchy(Node parent, 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<Object>(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 protocol buffer: got abstract node" + n); + } + for (AvroNode child : n.getChildren()) { + parseSubHierarchy(parsed, child); + } + } + + + @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) { + throw new IllegalStateException("When reading protocol buffer node " + + n.getFullName() + " does not exist. Full record is " + n, e); + } + for (final String impl : cn.getImplFullNames()) { + try { + iface.putImpl((ClassNode) getNode(impl)); + } catch (NameResolutionException e) { + throw new IllegalStateException("When reading protocol buffer node " + + n + " refers to non-existent implementation:" + impl); + } catch (ClassCastException e) { + try { + throw new IllegalStateException( + "When reading protocol buffer node " + n + + " found implementation" + getNode(impl) + + " which is not a ClassNode!"); + } catch (NameResolutionException e2) { + throw new IllegalStateException( + "Got 'cant happen' exception when producing error message for " + + e); + } + } + } + } + + 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(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)); + // TODO : Does the order not matter here? + } + } + + 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()); + } + // TODO What if n is the package node? + } + } + return this; + } + + @Override + public Node getNamespace() { + return namespace; + } +}
