private <T, U> Node buildPathToNode(final Class<U> clazz) throws ClassHierarchyException { final String[] path = clazz.getName().split("\\$"); Node root = namespace; for (int i = 0; i < path.length - 1; i++) { root = root.get(path[i]); } if (root == null) { throw new NullPointerException(); } final Node parent = root; final Type argType = ReflectionUtilities.getNamedParameterTargetOrNull(clazz); if (argType == null) { return JavaNodeFactory.createClassNode(parent, clazz); } else { // checked inside of NamedParameterNode, using reflection. @SuppressWarnings("unchecked") final NamedParameterNode<T> np = JavaNodeFactory.createNamedParameterNode( parent, (Class<? extends Name<T>>) clazz, argType); if (parameterParser.canParse(ReflectionUtilities.getFullName(argType)) && clazz.getAnnotation(NamedParameter.class).default_class() != Void.class) { throw new ClassHierarchyException( "Named parameter " + ReflectionUtilities.getFullName(clazz) + " defines default implementation for parsable type " + ReflectionUtilities.getFullName(argType)); } final String shortName = np.getShortName(); if (shortName != null) { final NamedParameterNode<?> oldNode = shortNames.get(shortName); if (oldNode != null) { if (oldNode.getFullName().equals(np.getFullName())) { throw new IllegalStateException( "Tried to double bind " + oldNode.getFullName() + " to short name " + shortName); } throw new ClassHierarchyException( "Named parameters " + oldNode.getFullName() + " and " + np.getFullName() + " have the same short name: " + shortName); } shortNames.put(shortName, np); } return np; } }
private static ClassHierarchyProto.Node serializeNode(Node n) { List<ClassHierarchyProto.Node> children = new ArrayList<>(); for (Node child : n.getChildren()) { children.add(serializeNode(child)); } if (n instanceof ClassNode) { ClassNode<?> cn = (ClassNode<?>) n; ConstructorDef<?>[] injectable = cn.getInjectableConstructors(); ConstructorDef<?>[] all = cn.getAllConstructors(); List<ConstructorDef<?>> others = new ArrayList<>(Arrays.asList(all)); others.removeAll(Arrays.asList(injectable)); List<ClassHierarchyProto.ConstructorDef> injectableConstructors = new ArrayList<>(); for (ConstructorDef<?> inj : injectable) { injectableConstructors.add(serializeConstructorDef(inj)); } List<ClassHierarchyProto.ConstructorDef> otherConstructors = new ArrayList<>(); for (ConstructorDef<?> other : others) { otherConstructors.add(serializeConstructorDef(other)); } List<String> implFullNames = new ArrayList<>(); for (ClassNode<?> impl : cn.getKnownImplementations()) { implFullNames.add(impl.getFullName()); } return newClassNode( cn.getName(), cn.getFullName(), cn.isInjectionCandidate(), cn.isExternalConstructor(), cn.isUnit(), injectableConstructors, otherConstructors, implFullNames, children); } else if (n instanceof NamedParameterNode) { NamedParameterNode<?> np = (NamedParameterNode<?>) n; return newNamedParameterNode( np.getName(), np.getFullName(), np.getSimpleArgName(), np.getFullArgName(), np.isSet(), np.isList(), np.getDocumentation(), np.getShortName(), 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); } }
@Override public ClassHierarchy merge(ClassHierarchy ch) { if (this == ch) { return this; } if (!(ch instanceof ProtocolBufferClassHierarchy)) { throw new UnsupportedOperationException( "Cannot merge with class hierarchies of type: " + ch.getClass().getName()); } final ProtocolBufferClassHierarchy pch = (ProtocolBufferClassHierarchy) ch; for (final String key : pch.lookupTable.keySet()) { if (!this.lookupTable.containsKey(key)) { this.lookupTable.put(key, pch.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; }