| 198 | } |
| 199 | |
| 200 | void RenderFactoryMethods(const OpSpec& op, const Type& op_class, |
| 201 | SourceWriter* writer) { |
| 202 | Method factory = Method::Create("create", op_class); |
| 203 | Javadoc factory_doc = |
| 204 | Javadoc::Create("Factory method to create a class wrapping a new " + |
| 205 | op_class.name() + " operation."); |
| 206 | Variable scope = |
| 207 | Variable::Create("scope", Type::Class("Scope", "org.tensorflow.op")); |
| 208 | AddArgument(scope, "current scope", &factory, &factory_doc); |
| 209 | for (const ArgumentSpec& input : op.inputs()) { |
| 210 | AddArgument(input.var(), input.description(), &factory, &factory_doc); |
| 211 | } |
| 212 | std::map<string, Type> default_types; |
| 213 | for (const AttributeSpec& attr : op.attributes()) { |
| 214 | AddArgument(attr.var(), attr.description(), &factory, &factory_doc); |
| 215 | // If this attribute is a type with a default value, save its value |
| 216 | // for passing it implicitly in a secondary factory method |
| 217 | if (attr.has_default_value() && attr.type().kind() == Type::GENERIC) { |
| 218 | Type default_type = Type::ForDataType(attr.default_value()->type()); |
| 219 | if (!default_type.wildcard()) { |
| 220 | default_types.insert(std::make_pair(attr.type().name(), default_type)); |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | if (!op.optional_attributes().empty()) { |
| 225 | AddArgument(Variable::Varargs("options", Type::Class("Options")), |
| 226 | "carries optional attributes values", &factory, &factory_doc); |
| 227 | } |
| 228 | factory_doc.add_tag("return", "a new instance of " + op_class.name()); |
| 229 | |
| 230 | writer->BeginMethod(factory, PUBLIC | STATIC, &factory_doc); |
| 231 | writer->Append("OperationBuilder opBuilder = scope.env().opBuilder(\"" + |
| 232 | op.graph_op_name() + "\", scope.makeOpName(\"" + |
| 233 | op_class.name() + "\"));"); |
| 234 | writer->EndLine(); |
| 235 | for (const ArgumentSpec& input : op.inputs()) { |
| 236 | if (input.iterable()) { |
| 237 | writer->Append("opBuilder.addInputList(Operands.asOutputs(" + |
| 238 | input.var().name() + "));"); |
| 239 | writer->EndLine(); |
| 240 | } else { |
| 241 | writer->Append("opBuilder.addInput(" + input.var().name() + |
| 242 | ".asOutput());"); |
| 243 | writer->EndLine(); |
| 244 | } |
| 245 | } |
| 246 | // Add control dependencies, if any. |
| 247 | writer->Append("opBuilder = scope.applyControlDependencies(opBuilder);"); |
| 248 | writer->EndLine(); |
| 249 | |
| 250 | for (const AttributeSpec& attribute : op.attributes()) { |
| 251 | WriteSetAttrDirective(attribute, false, writer); |
| 252 | } |
| 253 | if (!op.optional_attributes().empty()) { |
| 254 | writer->BeginBlock("if (options != null)") |
| 255 | .BeginBlock("for (Options opts : options)"); |
| 256 | for (const AttributeSpec& attribute : op.optional_attributes()) { |
| 257 | writer->BeginBlock("if (opts." + attribute.var().name() + " != null)"); |
no test coverage detected