2 #define _CRT_SECURE_NO_DEPRECATE
12 //==========================================================================
16 bbfyException(const std::string& message) : mMessage(message) {}
20 //==========================================================================
22 //==========================================================================
26 bbfy(const std::string& filename, const std::string& output_path = "",
27 bool verbose = false);
29 void CreateBlackBox();
34 void WriteGenericITKFilterHeader();
36 void BeginNamespace();
41 std::string mFilename;
42 std::string mOutputPath;
50 itkImageToImageFilter,
56 std::string mParentBlackBox;
57 std::string mItkParent;
58 std::string mVtkParent;
61 std::string mDescription;
62 std::string mCategory;
65 std::string mNamespace;
66 // int mNbTemplateParam;
67 std::vector<std::string> mTemplateParam;
68 std::string mTemplateDeclaration;
69 std::string mTemplateImplementation;
71 std::vector<std::string> mInclude;
73 std::string mUserConstructor;
74 std::string mUserCopyConstructor;
75 std::string mUserDestructor;
83 std::string generic_type;
87 std::vector<IO> mInput;
88 std::vector<IO> mOutput;
98 //==========================================================================
102 //==========================================================================
103 bbfy::bbfy(const std::string& filename,
104 const std::string& output_path,
107 mFilename = filename;
108 mOutputPath = output_path;
113 //==========================================================================
115 //==========================================================================
116 void bbfy::CreateBlackBox()
118 // Parse XML input file
120 // Create output files
124 //==========================================================================
127 //==========================================================================
128 void GetTextOrClear(const XMLNode& node, std::string& var)
132 var = node.getText();
134 else if (node.nClear()>0)
136 var = node.getClear().lpszValue;
140 std::string mess("Error : element <");
141 mess += node.getName();
142 mess += "> : no text nor <PRE></PRE> clear tag found";
143 throw bbfyException(mess);
146 //==========================================================================
149 //==========================================================================
150 void bbfy::ParseXML()
152 XMLResults* res = new XMLResults;
153 XMLNode BB = XMLNode::parseFile(mFilename.c_str(),"blackbox",res);
155 if ( res->error != eXMLErrorNone )
157 std::ostringstream str;
158 str << XMLNode::getError(res->error);
159 str << " [line " << res->nLine << ", col "<<res->nColumn<<"]";
161 throw bbfyException(str.str());
166 if (!BB.isAttributeSet("name"))
168 throw bbfyException("Error : no 'name' attribute found (mandatory)");
170 mName = BB.getAttribute("name");
172 if (mVerbose) std::cout << "* Creating BlackBox '"<<mName<<"'"<<std::endl;
177 if (BB.isAttributeSet("type"))
179 std::string bbtype = BB.getAttribute("type");
180 if (bbtype=="standard")
185 else if (bbtype=="itkImageToImageFilter")
187 mType = itkImageToImageFilter;
188 // Looks for <itkparent> tag
189 if (!BB.nChildNode("itkparent"))
191 throw bbfyException("Error : blackbox type 'itkImageToImageFilter' but no <itkparent> tag found (mandatory)");
193 GetTextOrClear(BB.getChildNode("itkparent"),mItkParent);
196 if (BB.isAttributeSet("generic")) mGeneric=true;
198 else if ((bbtype=="vtkImageAlgorithm") || (bbtype=="vtkPolyDataAlgorithm"))
200 mType = vtkImageAlgorithm;
201 // Looks for <vtkparent> tag
202 if (!BB.nChildNode("vtkparent"))
204 throw bbfyException("Error : blackbox type 'vtkImageAlgorithm' but no <vtkparent> tag found (mandatory)");
206 GetTextOrClear(BB.getChildNode("vtkparent"),mVtkParent);
211 std::string mess("Error : blackbox type '");
213 mess += "' unknown (types are 'standard','itkfilter')";
214 throw bbfyException(mess);
219 if (!BB.nChildNode("parentblackbox"))
221 throw bbfyException("Error : no <parentblackbox> tag found (mandatory)");
223 GetTextOrClear(BB.getChildNode("parentblackbox"),mParentBlackBox);
226 if (!BB.nChildNode("package"))
228 throw bbfyException("Error : no <package> tag found (mandatory)");
230 GetTextOrClear(BB.getChildNode("package"),mPackage);
234 for (i=0,j=0; i<BB.nChildNode("author"); i++)
237 GetTextOrClear(BB.getChildNode("author",&j),val);
242 for (i=0,j=0; i<BB.nChildNode("description"); i++)
245 GetTextOrClear(BB.getChildNode("description",&j),val);
250 for (i=0,j=0; i<BB.nChildNode("category"); i++)
253 GetTextOrClear(BB.getChildNode("category",&j),val);
258 mIsInNamespace = false;
259 if (BB.nChildNode("namespace"))
261 mIsInNamespace = true;
262 GetTextOrClear(BB.getChildNode("namespace"),mNamespace);
265 // UserConstructor body
266 if (BB.nChildNode("constructor"))
268 GetTextOrClear(BB.getChildNode("constructor"),mUserConstructor);
270 // UserCopyConstructor body
271 if (BB.nChildNode("copyconstructor"))
273 GetTextOrClear(BB.getChildNode("copyconstructor"),mUserCopyConstructor);
275 // UserDestructor body
276 if (BB.nChildNode("destructor"))
278 GetTextOrClear(BB.getChildNode("destructor"),mUserDestructor);
281 // Template parameters
282 // mNbTemplateParam = BB.nChildNode("template");
284 if ( BB.nChildNode("template") > 0)
286 mTemplateDeclaration = "<";
287 mTemplateImplementation = "<";
289 for (i=0,j=0; i<BB.nChildNode("template")-1; i++)
291 mTemplateDeclaration += "class ";
293 GetTextOrClear(BB.getChildNode("template",&j),val);
294 mTemplateDeclaration += val;
295 mTemplateDeclaration += ",";
296 mTemplateImplementation += val;
297 mTemplateImplementation += ",";
298 mTemplateParam.push_back(val);
300 mTemplateDeclaration += "class ";
302 GetTextOrClear(BB.getChildNode("template",&j),val);
303 mTemplateDeclaration += val;
304 mTemplateDeclaration += ">";
305 mTemplateImplementation += val;
306 mTemplateImplementation += ">";
307 mTemplateParam.push_back(val);
311 for (i=0,j=0; i<BB.nChildNode("include"); i++)
314 GetTextOrClear(BB.getChildNode("include",&j),val);
315 mInclude.push_back(val);
319 for (i=0,j=0; i<BB.nChildNode("input"); i++)
321 XMLNode n = BB.getChildNode("input",&j);
322 if (!n.isAttributeSet("name"))
324 throw bbfyException("Error : <input> attribute 'name' not found (mandatory)");
326 if (!n.isAttributeSet("type"))
328 throw bbfyException("Error : <input> attribute 'type' not found (mandatory)");
332 io.name = n.getAttribute("name");
333 io.type = n.getAttribute("type");
334 GetTextOrClear(n,io.help);
336 if (n.isAttributeSet("special"))
338 io.special = n.getAttribute("special");
341 if (n.isAttributeSet("generic_type"))
343 io.generic_type = n.getAttribute("generic_type");
346 mInput.push_back(io);
350 for (i=0,j=0; i<BB.nChildNode("output"); i++)
352 XMLNode n = BB.getChildNode("output",&j);
353 if (!n.isAttributeSet("name"))
355 throw bbfyException("Error : <output> attribute 'name' not found (mandatory)");
357 if (!n.isAttributeSet("type"))
359 throw bbfyException("Error : <output> attribute 'type' not found (mandatory)");
363 io.name = n.getAttribute("name");
364 io.type = n.getAttribute("type");
365 GetTextOrClear(n,io.help);
367 if (n.isAttributeSet("special"))
369 io.special = n.getAttribute("special");
372 if (n.isAttributeSet("generic_type"))
374 io.generic_type = n.getAttribute("generic_type");
377 mOutput.push_back(io);
382 // Process tag given ?
383 if (BB.nChildNode("process"))
385 GetTextOrClear(BB.getChildNode("process"),mProcess);
388 //==========================================================================
391 //==========================================================================
392 void bbfy::BeginNamespace()
396 mFile << "namespace "<<mNamespace <<"\n{\n\n";
399 //==========================================================================
401 //==========================================================================
402 void bbfy::EndNamespace()
406 mFile << "}\n// EO namespace "<<mNamespace<<"\n\n";
409 //==========================================================================
412 //==========================================================================
413 void bbfy::CreateHeader()
420 if (mVerbose) std::cout << " - Creating header '"<<mHName<<"'"<<std::endl;
421 std::string fullname = mOutputPath + mHName;
422 mFile.open(fullname.c_str());
425 std::string mess("Error : could not open file \"");
426 mess += fullname + "\"";
427 throw bbfyException(mess);
432 mFile << "#include \"bbtkUserBlackBox.h\"\n";
433 std::vector<std::string>::iterator i;
434 for (i=mInclude.begin(); i!=mInclude.end(); ++i)
436 mFile << "#include \"" << *i <<"\"\n";
438 if (mGeneric) mFile << "#include \"bbitkImage.h\"\n";
446 // If it is a template class
447 if (mTemplateParam.size() > 0)
449 mFile << "template " << mTemplateDeclaration <<"\n";
452 // Class declaration and parents
453 mFile << "class /*BBTK_EXPORT*/ "<<mName<<"\n";
455 mFile << " public "<<mParentBlackBox;
458 if (mBB.nChildNode("inherits"))
461 for (i=0,j=0; i<mBB.nChildNode("inherits")-1; i++)
464 << mBB.getChildNode("inherits",&j).getText()
468 << mBB.getChildNode("Inherits",&j).getText()
473 if (mType == itkImageToImageFilter )
475 mFile << ",\n public " << mItkParent <<"\n";
477 else if ( (mType == vtkImageAlgorithm) ||
478 (mType == vtkPolyDataAlgorithm) )
480 mFile << ",\n public " << mVtkParent <<"\n";
490 mFile << " BBTK_USER_BLACK_BOX_INTERFACE("
492 << mParentBlackBox << ");\n";
494 // typedef on itkfilter
495 if (mType == itkImageToImageFilter)
497 mFile << " typedef " <<mItkParent <<" itkParent;"<<std::endl;
498 mFile << " void bbDelete() { itkParent::UnRegister(); }"<<std::endl;
500 // typedef on itkfilter
501 if ( (mType == vtkImageAlgorithm) ||
502 (mType == vtkPolyDataAlgorithm) )
504 mFile << " typedef " <<mVtkParent <<" vtkParent;"<<std::endl;
505 mFile << " void bbDelete() { vtkParent::Delete(); }"<<std::endl;
508 // Declare user constructor / copy cons /destr
509 mFile << "//=================================================================="<<std::endl;
510 mFile << "/// User callback called in the box contructor"<<std::endl;
512 mFile << "virtual void bbUserConstructor();"<<std::endl;
513 mFile << "/// User callback called in the box copy constructor"<<std::endl;
514 mFile << "virtual void bbUserCopyConstructor();"<<std::endl;
515 mFile << "/// User callback called in the box destructor"<<std::endl;
516 mFile << "virtual void bbUserDestructor();"<<std::endl;
517 mFile << "//=================================================================="<<std::endl;
522 std::vector<IO>::iterator ioi;
523 for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi)
525 if (ioi->special=="")
527 mFile << " BBTK_DECLARE_INPUT("
533 else if (ioi->special=="itk input")
535 mFile << " BBTK_DECLARE_ITK_INPUT("
542 else if (ioi->special=="vtk input")
544 if (mType == vtkImageAlgorithm) {
545 mFile << " BBTK_DECLARE_VTK_IMAGE_ALGORITHM_INPUT("
552 else if (mType == vtkPolyDataAlgorithm) {
553 mFile << " BBTK_DECLARE_POLY_DATA_ALGORITHM_INPUT("
561 else if (ioi->special=="itk parameter")
563 mFile << " BBTK_DECLARE_ITK_PARAM("
570 else if (ioi->special=="vtk parameter")
572 mFile << " BBTK_DECLARE_VTK_PARAM("
581 std::string mess("Error : input '");
583 mess += "', 'special' attribute '";
584 mess += ioi->special;
586 throw bbfyException(mess);
591 for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi)
593 if (ioi->special=="")
595 mFile << " BBTK_DECLARE_OUTPUT("
601 else if (ioi->special=="itk output")
603 mFile << " BBTK_DECLARE_ITK_OUTPUT("
610 else if (ioi->special=="vtk output")
612 mFile << " BBTK_DECLARE_VTK_OUTPUT("
621 std::string mess("Error : output '");
623 mess += "', 'special' attribute '";
624 mess += ioi->special;
626 throw bbfyException(mess);
632 if ((mType == STD)||(mProcess.size()))
634 mFile << " BBTK_PROCESS(DoProcess);\n" ;
635 mFile << " void DoProcess();\n";
637 else if (mType == itkImageToImageFilter)
639 mFile << " BBTK_PROCESS(itkParent::Update);\n" ;
641 else if ((mType == vtkImageAlgorithm) ||
642 (mType == vtkPolyDataAlgorithm) )
645 mFile << " BBTK_PROCESS(vtkParent::Update);\n" ;
648 // EO black box declaration
653 // BO black box description
654 if (mTemplateParam.size()==0)
656 mFile << "BBTK_BEGIN_DESCRIBE_BLACK_BOX("
658 << mParentBlackBox << ");\n";
659 mFile << "BBTK_NAME(\"" << mName <<"\");\n";
661 else if (mTemplateParam.size()==1)
663 mFile << "BBTK_BEGIN_DESCRIBE_TEMPLATE_BLACK_BOX("
665 //<< mParentBlackBox //<< ","
666 // << mTemplateParam[0]
668 mFile << "BBTK_NAME(\"" << mName
669 << "<\"+bbtk::TypeName<" << mTemplateParam[0]
674 throw bbfyException("template bb with more than 1 templ param not impl");
678 mFile << "BBTK_AUTHOR(\""<<mAuthor<< "\");\n";
681 mFile << "BBTK_DESCRIPTION(\""<<mDescription<< "\");\n";
684 mFile << "BBTK_CATEGORY(\""<<mCategory<< "\");\n";
687 for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi)
689 if (mTemplateParam.size()>0)
691 mFile << "BBTK_TEMPLATE_INPUT(";
695 mFile << "BBTK_INPUT(";
697 mFile << mName << "," << ioi->name << ",\""
698 << ioi->help << "\"," << ioi->type <<");\n";
702 for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi)
704 if (mTemplateParam.size()>0)
706 mFile << "BBTK_TEMPLATE_OUTPUT(";
710 mFile << "BBTK_OUTPUT(";
712 mFile << mName << "," << ioi->name << ",\""
713 << ioi->help << "\"," << ioi->type <<");\n";
716 // EO black box description
717 if (mTemplateParam.size()==0)
719 mFile << "BBTK_END_DESCRIBE_BLACK_BOX("
722 else if (mTemplateParam.size()==1)
724 mFile << "BBTK_END_DESCRIBE_TEMPLATE_BLACK_BOX("
726 // << mTemplateParam[0]
731 throw bbfyException("template bb with more than 1 templ param not impl");
735 // Untemplatization of itk filters
738 WriteGenericITKFilterHeader();
750 //==========================================================================
754 //==========================================================================
755 void bbfy::WriteGenericITKFilterHeader()
757 mFile << "\n//===================================================\n";
758 mFile << "// Generic \"untemplatized\" filter\n";
759 mFile << "//===================================================\n";
761 // Class declaration and parents
762 mFile << "class /*BBTK_EXPORT*/ "<<mName<<"Generic\n";
764 mFile << " public bbtk::UserBlackBox\n";
768 mFile << " BBTK_USER_BLACK_BOX_INTERFACE("
769 << mName << "Generic,bbtk::UserBlackBox);\n";
772 std::vector<IO>::iterator ioi;
773 for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi)
775 mFile << " BBTK_DECLARE_INPUT("
783 for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi)
785 mFile << " BBTK_DECLARE_OUTPUT("
793 mFile << " BBTK_PROCESS(ProcessSwitch);\n";
794 mFile << " private :\n";
795 mFile << " inline void ProcessSwitch();\n";
796 mFile << " template <class T, unsigned int D> void Process();\n";
797 // EO black box declaration
802 // BO black box description
803 mFile << "BBTK_BEGIN_DESCRIBE_BLACK_BOX("
804 << mName << "Generic,bbtk::UserBlackBox);\n";
805 mFile << "BBTK_NAME(\"" << mName <<"\");\n";
808 mFile << "BBTK_AUTHOR(\""<<mAuthor<< "\");\n";
811 mFile << "BBTK_DESCRIPTION(\""<<mDescription<< "\");\n";
814 for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi)
816 mFile << "BBTK_INPUT(";
817 mFile << mName << "Generic," << ioi->name << ",\""
818 << ioi->help << "\"," << ioi->generic_type <<");\n";
822 for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi)
824 mFile << "BBTK_OUTPUT(";
825 mFile << mName << "Generic," << ioi->name << ",\""
826 << ioi->help << "\"," << ioi->generic_type <<");\n";
829 // EO black box description
830 mFile << "BBTK_END_DESCRIBE_BLACK_BOX("
831 << mName << "Generic);\n";
834 //=================================================================
835 // ProcessSwitch implementation
836 mFile << "void "<< mName <<"Generic::ProcessSwitch()\n"
838 << "CALL_FOR_ALL_TYPES_AND_DIM(bbGetInputIn()->GetType(),\n"
839 << " bbGetInputIn()->GetDimension(),\n"
842 //=================================================================
845 //=================================================================
846 // Template process implementation
847 mFile << "template <class T, unsigned int D>\n"
848 << "void "<<mName<<"Generic::Process()\n"
850 << " bbtkDebugMessageInc(\"Kernel\",9,\n"
852 << "Generic::Process<\"<<TypeName<T>()<<\",\"<<D<<\">()\"<<std::endl);\n"
854 << " typedef itk::Image<T,D> ImageType;\n"
855 << " typedef "<<mName<<"<ImageType> FilterType;\n"
857 << " FilterType* f = new FilterType(\"Temp\");\n"
859 << " f->bbSetInputIn( this->bbGetInputIn()->GetImage<T,D>() );\n";
861 for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi)
863 if (ioi->name == "In") continue;
864 mFile << " f->bbSetInput"<<ioi->name<<" ( this->bbGetInput"
865 << ioi->name << "() );\n";
868 mFile << " f->bbUpdate();\n"
869 << " this->bbSetOutputOut( new itkImage( f->bbGetOutputOut() ) );\n"
870 << " f->UnRegister();\n"
871 << " bbtkDebugDecTab(\"Kernel\",9);\n"
873 //=================================================================
877 //==========================================================================
880 //==========================================================================
881 void bbfy::CreateCode()
884 mCxxName += mPackage;
887 if (mVerbose) std::cout << " - Creating code '"<<mCxxName<<"'"<<std::endl;
888 std::string fullname = mOutputPath + mCxxName;
889 mFile.open(fullname.c_str());
892 std::string mess("Error : could not open file \"");
895 throw bbfyException(mess);
899 // Header of the class
900 mFile << "#include \"" << mHName << "\"\n";
902 // Include Package header
903 mFile << "#include \"bb"<<mPackage << "Package.h\"\n";
910 if (mTemplateParam.size()>0)
913 mFile << "BBTK_USER_BLACK_BOX_TEMPLATE_IMPLEMENTATION("
915 << mParentBlackBox << ");\n";
920 mFile << "BBTK_USER_BLACK_BOX_IMPLEMENTATION("
921 << mName << "Generic,bbtk::UserBlackBox);\n";
923 mFile << "BBTK_ADD_BLACK_BOX_TO_PACKAGE("
925 << mName << "Generic)\n";
930 // Non template class
932 mFile << "BBTK_ADD_BLACK_BOX_TO_PACKAGE("
937 mFile << "BBTK_USER_BLACK_BOX_IMPLEMENTATION("
939 << mParentBlackBox << ");\n";
942 if ((mType == STD)||(mProcess.size()))
944 mFile << "void "<<mName<<"::DoProcess()\n{\n";
945 mFile << mProcess << "\n";
950 // User constr / copy constr / destr implementation
951 mFile <<"void "<<mName<<"::bbUserConstructor()"<<std::endl;
952 mFile << "{"<<std::endl;
953 //mFile<<"bbtkDebugMessage(\"Kernel\",9,\""<<mName<<::bbUserConstructor()"<<std::endl);"<<std::endl;
954 mFile << mUserConstructor << std::endl;
955 mFile << "}" << std::endl;
957 mFile <<"void "<<mName<<"::bbUserCopyConstructor()"<<std::endl;
958 mFile << "{"<<std::endl;
959 //mFile<<"bbtkDebugMessage(\"Kernel\",9,\""<<mName<<::bbUserCopyConstructor()"<<std::endl);"<<std::endl;
960 mFile << mUserCopyConstructor << std::endl;
961 mFile << "}" << std::endl;
963 mFile <<"void "<<mName<<"::bbUserDestructor()"<<std::endl;
964 mFile << "{"<<std::endl;
965 //mFile<<"bbtkDebugMessage(\"Kernel\",9,\""<<mName<<::bbUserDestructor()"<<std::endl);"<<std::endl;
966 mFile << mUserDestructor << std::endl;
967 mFile << "}" << std::endl;
979 //==========================================================================
985 //==========================================================================
986 int main(int argc, char **argv)
989 if (argc<2 || argc>4)
991 std::cerr << "usage : "<< argv[0] <<" xml_file [output_path] [-q]" << std::endl;
997 std::string output_path("");
999 if (argc>2) output_path = argv[2];
1000 if (argc>3) verbose = false;
1002 bbfy B(argv[1],output_path,verbose);
1004 catch (bbfyException e)
1006 std::cerr << e.mMessage << std::endl;
1011 //==========================================================================