001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.tang.implementation.protobuf; 020 021import org.apache.reef.tang.ClassHierarchy; 022import org.apache.reef.tang.exceptions.BindException; 023import org.apache.reef.tang.exceptions.NameResolutionException; 024import org.apache.reef.tang.implementation.Constructor; 025import org.apache.reef.tang.implementation.InjectionPlan; 026import org.apache.reef.tang.implementation.Subplan; 027import org.apache.reef.tang.implementation.java.JavaInstance; 028import org.apache.reef.tang.proto.InjectionPlanProto; 029import org.apache.reef.tang.types.ClassNode; 030import org.apache.reef.tang.types.ConstructorDef; 031import org.apache.reef.tang.types.Node; 032 033import java.util.Arrays; 034import java.util.List; 035 036public class ProtocolBufferInjectionPlan { 037 038 <T> InjectionPlanProto.InjectionPlan newConstructor(final String fullName, 039 final List<InjectionPlanProto.InjectionPlan> plans) { 040 return InjectionPlanProto.InjectionPlan 041 .newBuilder() 042 .setName(fullName) 043 .setConstructor( 044 InjectionPlanProto.Constructor.newBuilder().addAllArgs(plans) 045 .build()).build(); 046 } 047 048 <T> InjectionPlanProto.InjectionPlan newSubplan(final String fullName, 049 final int selectedPlan, 050 final List<InjectionPlanProto.InjectionPlan> plans) { 051 return InjectionPlanProto.InjectionPlan 052 .newBuilder() 053 .setName(fullName) 054 .setSubplan( 055 InjectionPlanProto.Subplan.newBuilder() 056 .setSelectedPlan(selectedPlan).addAllPlans(plans).build()) 057 .build(); 058 } 059 060 <T> InjectionPlanProto.InjectionPlan newInstance(final String fullName, 061 final String value) { 062 return InjectionPlanProto.InjectionPlan.newBuilder().setName(fullName) 063 .setInstance(InjectionPlanProto.Instance.newBuilder().setValue(value)) 064 .build(); 065 } 066 067 public <T> InjectionPlanProto.InjectionPlan serialize(final InjectionPlan<T> ip) { 068 if (ip instanceof Constructor) { 069 final Constructor<T> cons = (Constructor<T>) ip; 070 final InjectionPlan<?>[] args = cons.getArgs(); 071 final InjectionPlanProto.InjectionPlan[] protoArgs = new InjectionPlanProto.InjectionPlan[args.length]; 072 for (int i = 0; i < args.length; i++) { 073 protoArgs[i] = serialize(args[i]); 074 } 075 return newConstructor(ip.getNode().getFullName(), 076 Arrays.asList(protoArgs)); 077 } else if (ip instanceof Subplan) { 078 final Subplan<T> sp = (Subplan<T>) ip; 079 final InjectionPlan<?>[] args = sp.getPlans(); 080 final InjectionPlanProto.InjectionPlan[] subPlans = new InjectionPlanProto.InjectionPlan[args.length]; 081 for (int i = 0; i < args.length; i++) { 082 subPlans[i] = serialize(args[i]); 083 } 084 return newSubplan(ip.getNode().getFullName(), sp.getSelectedIndex(), 085 Arrays.asList(subPlans)); 086 } else if (ip instanceof JavaInstance) { 087 final JavaInstance<T> ji = (JavaInstance<T>) ip; 088 return newInstance(ip.getNode().getFullName(), ji.getInstanceAsString()); 089 } else { 090 throw new IllegalStateException( 091 "Encountered unknown type of InjectionPlan: " + ip); 092 } 093 } 094 095 private Object parse(final String type, final String value) { 096 // XXX this is a placeholder for now. We need a parser API that will 097 // either produce a live java object or (partially) validate stuff to 098 // see if it looks like the target language will be able to handle this 099 // type + value. 100 return value; 101 } 102 103 @SuppressWarnings("unchecked") 104 public <T> InjectionPlan<T> deserialize(final ClassHierarchy ch, 105 final InjectionPlanProto.InjectionPlan ip) throws NameResolutionException, 106 BindException { 107 final String fullName = ip.getName(); 108 if (ip.hasConstructor()) { 109 final InjectionPlanProto.Constructor cons = ip.getConstructor(); 110 111 final ClassNode<T> cn = (ClassNode<T>) ch.getNode(fullName); 112 113 final InjectionPlanProto.InjectionPlan[] protoBufArgs = cons 114 .getArgsList().toArray(new InjectionPlanProto.InjectionPlan[0]); 115 final ClassNode<?>[] cnArgs = new ClassNode[protoBufArgs.length]; 116 117 for (int i = 0; i < protoBufArgs.length; i++) { 118 cnArgs[i] = (ClassNode<?>) ch.getNode(protoBufArgs[i].getName()); 119 } 120 121 final InjectionPlan<?>[] ipArgs = new InjectionPlan[protoBufArgs.length]; 122 123 for (int i = 0; i < protoBufArgs.length; i++) { 124 ipArgs[i] = deserialize(ch, protoBufArgs[i]); 125 } 126 127 final ConstructorDef<T> constructor = cn.getConstructorDef(cnArgs); 128 return new Constructor<T>(cn, constructor, ipArgs); 129 } else if (ip.hasInstance()) { 130 final InjectionPlanProto.Instance ins = ip.getInstance(); 131 final T instance = (T) parse(ip.getName(), ins.getValue()); 132 return new JavaInstance<T>(ch.getNode(ip.getName()), instance); 133 } else if (ip.hasSubplan()) { 134 final InjectionPlanProto.Subplan subplan = ip.getSubplan(); 135 final InjectionPlanProto.InjectionPlan[] protoBufPlans = subplan 136 .getPlansList().toArray(new InjectionPlanProto.InjectionPlan[0]); 137 138 final InjectionPlan<T>[] subPlans = new InjectionPlan[protoBufPlans.length]; 139 for (int i = 0; i < protoBufPlans.length; i++) { 140 subPlans[i] = deserialize(ch, protoBufPlans[i]); 141 } 142 final Node n = ch.getNode(fullName); 143 return new Subplan<T>(n, subPlans); 144 } else { 145 throw new IllegalStateException( 146 "Encountered unknown type of injection plan: " + ip); 147 } 148 } 149}