#ifdef WIN32 #define _CRT_SECURE_NO_DEPRECATE #endif #include #include "xmlParser.h" #include #include #include #include //========================================================================== class bbfyException { public: bbfyException(const std::string& message) : mMessage(message) {} std::string mMessage; }; //========================================================================== //========================================================================== class bbfy { public: bbfy(const std::string& filename, const std::string& output_path = "", bool verbose = false); void CreateBlackBox(); void ParseXML(); void CreateHeader(); void CreateCode(); void WriteGenericITKFilterHeader(); void BeginNamespace(); void EndNamespace(); private: // std::string mFilename; std::string mOutputPath; bool mVerbose; // std::string mName; typedef enum { STD, itkImageToImageFilter, vtkImageAlgorithm, vtkPolyDataAlgorithm, } BoxType; BoxType mType; std::string mParentBlackBox; std::string mItkParent; std::string mVtkParent; bool mGeneric; std::string mAuthor; std::string mDescription; std::string mPackage; bool mIsInNamespace; std::string mNamespace; // int mNbTemplateParam; std::vector mTemplateParam; std::string mTemplateDeclaration; std::string mTemplateImplementation; std::vector mInclude; std::string mUserConstructor; std::string mUserCopyConstructor; std::string mUserDestructor; typedef struct { std::string name; std::string type; std::string help; std::string special; std::string generic_type; } IO; std::vector mInput; std::vector mOutput; std::string mProcess; // std::ofstream mFile; std::string mHName; std::string mCxxName; }; //========================================================================== //========================================================================== bbfy::bbfy(const std::string& filename, const std::string& output_path, bool verbose) { mFilename = filename; mOutputPath = output_path; mVerbose = verbose; CreateBlackBox(); } //========================================================================== //========================================================================== void bbfy::CreateBlackBox() { // Parse XML input file ParseXML(); // Create output files CreateHeader(); CreateCode(); } //========================================================================== //========================================================================== void GetTextOrClear(const XMLNode& node, std::string& var) { if (node.nText()>0) { var = node.getText(); } else if (node.nClear()>0) { var = node.getClear().lpszValue; } else { std::string mess("Error : element <"); mess += node.getName(); mess += "> : no text nor
 clear tag found";
      throw bbfyException(mess);
    }
}
//==========================================================================


//==========================================================================
void bbfy::ParseXML()
{
  XMLResults* res = new XMLResults;
  XMLNode BB = XMLNode::parseFile(mFilename.c_str(),"blackbox",res);

  if ( res->error != eXMLErrorNone ) 
    {
      std::ostringstream str;
      str << XMLNode::getError(res->error);
      str << " [line " << res->nLine << ", col "<nColumn<<"]"; 
      delete res;
      throw bbfyException(str.str());
    }
  delete res;

  // Name
  if (!BB.isAttributeSet("name")) 
    {
      throw bbfyException("Error : no 'name' attribute found (mandatory)");
    }
  mName = BB.getAttribute("name");

  if (mVerbose) std::cout << "* Creating BlackBox '"< tag
	  if (!BB.nChildNode("itkparent")) 
	    {
	      throw bbfyException("Error : blackbox type 'itkImageToImageFilter' but no  tag found (mandatory)");
	    }
	  GetTextOrClear(BB.getChildNode("itkparent"),mItkParent);
	  // 
	  mGeneric = false;
	  if (BB.isAttributeSet("generic")) mGeneric=true;
	}
      else if ((bbtype=="vtkImageAlgorithm") || (bbtype=="vtkPolyDataAlgorithm"))
	{
	  mType = vtkImageAlgorithm;
	  // Looks for  tag
	  if (!BB.nChildNode("vtkparent")) 
	    {
	      throw bbfyException("Error : blackbox type 'vtkImageAlgorithm' but no  tag found (mandatory)");
	    }
	  GetTextOrClear(BB.getChildNode("vtkparent"),mVtkParent);
	  // 
	}
      else 
	{
	  std::string mess("Error : blackbox type '");
	  mess += bbtype;
	  mess += "' unknown (types are 'standard','itkfilter')";
	  throw bbfyException(mess);
	}
    }

  // Parent black box
  if (!BB.nChildNode("parentblackbox")) 
    {
      throw bbfyException("Error : no  tag found (mandatory)");
   }
  GetTextOrClear(BB.getChildNode("parentblackbox"),mParentBlackBox);

  // Package
  if (!BB.nChildNode("package")) 
    {
      throw bbfyException("Error : no  tag found (mandatory)");
   }
  GetTextOrClear(BB.getChildNode("package"),mPackage);

  // Author
  int i,j;
  for (i=0,j=0; i 0)
    {
      mTemplateDeclaration = "<";
      mTemplateImplementation = "<";
      
      for (i=0,j=0; i attribute 'name' not found (mandatory)");
	}
      if (!n.isAttributeSet("type"))
	{
	  throw bbfyException("Error :  attribute 'type' not found (mandatory)");
	}

      IO io;
      io.name = n.getAttribute("name");
      io.type = n.getAttribute("type"); 
      GetTextOrClear(n,io.help);

      if (n.isAttributeSet("special")) 
	{
	  io.special =  n.getAttribute("special");  
	}

      if (n.isAttributeSet("generic_type")) 
	{
	  io.generic_type =  n.getAttribute("generic_type");  
	}

      mInput.push_back(io);
    }
  
  // Outputs
  for (i=0,j=0; i attribute 'name' not found (mandatory)");
	}
      if (!n.isAttributeSet("type"))
	{
	  throw bbfyException("Error :  attribute 'type' not found (mandatory)");
	}

      IO io;
      io.name = n.getAttribute("name"); 
      io.type = n.getAttribute("type"); 
      GetTextOrClear(n,io.help);

      if (n.isAttributeSet("special")) 
	{
	  io.special =  n.getAttribute("special");  
	}

      if (n.isAttributeSet("generic_type")) 
	{
	  io.generic_type =  n.getAttribute("generic_type");  
	}

      mOutput.push_back(io);
    }


  // Process
  // Process tag given ?
   if (BB.nChildNode("process"))
     {
       GetTextOrClear(BB.getChildNode("process"),mProcess);
     }
}
//==========================================================================


//==========================================================================
void bbfy::BeginNamespace()
{
  if (mIsInNamespace)
    {
      mFile << "namespace "<::iterator i;
  for (i=mInclude.begin(); i!=mInclude.end(); ++i) 
    {
      mFile << "#include \"" << *i <<"\"\n";
    }
  if (mGeneric) mFile << "#include \"bbitkImage.h\"\n";
  mFile << "\n";

  // Namespace
  BeginNamespace();

  // Interface

  // If it is a template class
  if (mTemplateParam.size() > 0)
    {
      mFile << "template " << mTemplateDeclaration <<"\n";
    }
  
  // Class declaration and parents
  mFile << "class /*BBTK_EXPORT*/ "<::iterator ioi;
  for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi) 
    {
      if (ioi->special=="") 
	{
	  mFile << "  BBTK_DECLARE_INPUT(" 
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	}
      else if (ioi->special=="itk input")
	{
	  mFile << "  BBTK_DECLARE_ITK_INPUT(" 
		<< "itkParent,"
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	}
      else if (ioi->special=="vtk input")
	{
	  if (mType == vtkImageAlgorithm) {
	  mFile << "  BBTK_DECLARE_VTK_IMAGE_ALGORITHM_INPUT(" 
		<< "vtkParent,"
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	  } 
	  else if (mType == vtkPolyDataAlgorithm) {
	  mFile << "  BBTK_DECLARE_POLY_DATA_ALGORITHM_INPUT(" 
		<< "vtkParent,"
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	  }
	}
      else if (ioi->special=="itk parameter")
	{
	  mFile << "  BBTK_DECLARE_ITK_PARAM(" 
		<< "itkParent,"
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	}
      else if (ioi->special=="vtk parameter")
	{
	  mFile << "  BBTK_DECLARE_VTK_PARAM(" 
		<< "vtkParent,"
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	}
      else 
	{
	  std::string mess("Error : input '");
	  mess += ioi->name;
	  mess += "', 'special' attribute '";
	  mess += ioi->special;
	  mess += "' unknown";
	  throw bbfyException(mess);
	}
    }
  
  // Outputs
  for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi) 
    {
      if (ioi->special=="") 
	{
	  mFile << "  BBTK_DECLARE_OUTPUT(" 
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	}
      else if (ioi->special=="itk output")
	{
	  mFile << "  BBTK_DECLARE_ITK_OUTPUT(" 
		<< "itkParent,"
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	}  
      else if (ioi->special=="vtk output")
	{
	  mFile << "  BBTK_DECLARE_VTK_OUTPUT(" 
		<< "vtkParent,"
		<< ioi->name
		<< ","
		<< ioi->type
		<< ");\n";
	}  
      else 
	{
	  std::string mess("Error : output '");
	  mess += ioi->name;
	  mess += "', 'special' attribute '";
	  mess += ioi->special;
	  mess += "' unknown";
	  throw bbfyException(mess);
	}
    }
  

  // Process
  if ((mType == STD)||(mProcess.size()))
    {
      mFile << "  BBTK_PROCESS(DoProcess);\n" ;
      mFile << "  void DoProcess();\n";
    }
  else if (mType == itkImageToImageFilter)
    {   
      mFile << "  BBTK_PROCESS(itkParent::Update);\n" ;
    }
  else if ((mType == vtkImageAlgorithm) ||
	   (mType == vtkPolyDataAlgorithm) )

    {   
      mFile << "  BBTK_PROCESS(vtkParent::Update);\n" ;
    }

  // EO black box declaration
  mFile << "};\n\n";



  // BO black box description
  if (mTemplateParam.size()==0)
    {
      mFile << "BBTK_BEGIN_DESCRIBE_BLACK_BOX("
	    << mName << ","
	    << mParentBlackBox << ");\n";
      mFile << "BBTK_NAME(\"" << mName <<"\");\n";
    }
  else if (mTemplateParam.size()==1)
    {
      mFile << "BBTK_BEGIN_DESCRIBE_TEMPLATE_BLACK_BOX("
	    << mName //<< ","
	//<< mParentBlackBox //<< ","
	//   << mTemplateParam[0] 
	    << ");\n";
      mFile << "BBTK_NAME(\"" << mName 
	    << "<\"+bbtk::TypeName<" << mTemplateParam[0]
	    <<">()+\">\");\n";
    }
 else 
    {
      throw bbfyException("template bb with more than 1 templ param not impl");
    } 
  
  // Author
  mFile << "BBTK_AUTHOR(\""<0)
	{
	  mFile << "BBTK_TEMPLATE_INPUT(";
	} 
      else 
	{
	  mFile << "BBTK_INPUT(";
	} 
      mFile << mName << "," << ioi->name << ",\""
	    << ioi->help << "\"," <<  ioi->type <<");\n";
    }
  
  // Outputs
  for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi) 
    {
      if (mTemplateParam.size()>0)
	{
	  mFile << "BBTK_TEMPLATE_OUTPUT(";
	} 
      else 
	{
	  mFile << "BBTK_OUTPUT(";
	} 
      mFile << mName << "," << ioi->name << ",\""
	    << ioi->help << "\"," <<  ioi->type <<");\n";
    }
  
  // EO black box description
  if (mTemplateParam.size()==0)
    {
      mFile << "BBTK_END_DESCRIBE_BLACK_BOX("
	    << mName << ");\n";
    }
  else if (mTemplateParam.size()==1)
    {
      mFile << "BBTK_END_DESCRIBE_TEMPLATE_BLACK_BOX("
	    << mName //<< ","
	// << mTemplateParam[0] 
	    << ");\n";
    }
  else 
    {
      throw bbfyException("template bb with more than 1 templ param not impl");
     
    } 
  
  // Untemplatization of itk filters
  if ( mGeneric )
    {
      WriteGenericITKFilterHeader();
    }


  // EO namespace
  EndNamespace();

  // EOF
  mFile << "\n";

  mFile.close();
}
//==========================================================================



//==========================================================================
void bbfy::WriteGenericITKFilterHeader()
{
  mFile << "\n//===================================================\n";
  mFile << "// Generic \"untemplatized\" filter\n";
  mFile << "//===================================================\n";

  // Class declaration and parents
  mFile << "class /*BBTK_EXPORT*/ "<::iterator ioi;
  for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi) 
    {
      mFile << "  BBTK_DECLARE_INPUT(" 
	    << ioi->name
	    << ","
	    << ioi->generic_type
	    << ");\n";
    }
  
  // Outputs
  for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi) 
    {
      mFile << "  BBTK_DECLARE_OUTPUT(" 
	    << ioi->name
	    << ","
	    << ioi->generic_type
	    << ");\n";
    }
    
  // Process
  mFile << "  BBTK_PROCESS(ProcessSwitch);\n";
  mFile << "  private :\n";
  mFile << "    inline void ProcessSwitch();\n";
  mFile << "    template  void Process();\n";
  // EO black box declaration
  mFile << "};\n\n";



  // BO black box description
  mFile << "BBTK_BEGIN_DESCRIBE_BLACK_BOX("
	<< mName << "Generic,bbtk::UserBlackBox);\n";
  mFile << "BBTK_NAME(\"" << mName <<"\");\n";

  // Author
  mFile << "BBTK_AUTHOR(\""<name << ",\""
	    << ioi->help << "\"," <<  ioi->generic_type <<");\n";
    }
  
  // Outputs
  for (ioi=mOutput.begin(); ioi!=mOutput.end(); ++ioi) 
    {
      mFile << "BBTK_OUTPUT(";
      mFile << mName << "Generic," << ioi->name << ",\""
	    << ioi->help << "\"," <<  ioi->generic_type <<");\n";
    }
  
  // EO black box description
  mFile << "BBTK_END_DESCRIBE_BLACK_BOX("
	<< mName << "Generic);\n";


  //=================================================================
  // ProcessSwitch implementation
  mFile << "void "<< mName <<"Generic::ProcessSwitch()\n"
	<< "{\n"
	<< "CALL_FOR_ALL_TYPES_AND_DIM(bbGetInputIn()->GetType(),\n"
	<< "                           bbGetInputIn()->GetDimension(),\n"
	<< "                           Process);\n"
	<< "}\n";
  //=================================================================


  //=================================================================
  // Template process implementation
  mFile << "template \n"
	<< "void "<()<<\",\"<()\"< ImageType;\n"
	<< "  typedef "< FilterType;\n"
    
	<< "  FilterType* f = new FilterType(\"Temp\");\n"
    
	<< "  f->bbSetInputIn( this->bbGetInputIn()->GetImage() );\n";
  
  for (ioi=mInput.begin(); ioi!=mInput.end(); ++ioi) 
    {
      if (ioi->name == "In") continue;
      mFile << "  f->bbSetInput"<name<<" ( this->bbGetInput" 
	    << ioi->name << "() );\n";
    }
  
  mFile << "  f->bbUpdate();\n"
	<< "  this->bbSetOutputOut( new itkImage( f->bbGetOutputOut() ) );\n"
	<< "  f->UnRegister();\n"
	<< "  bbtkDebugDecTab(\"Kernel\",9);\n"
	<< "}\n\n";
  //=================================================================


}
//==========================================================================


//==========================================================================
void bbfy::CreateCode()
{
  mCxxName = "bb";
  mCxxName += mPackage;
  mCxxName += mName;
  mCxxName += ".cxx";
  if (mVerbose) std::cout << " - Creating code   '"<0) 
    {
      // Implementation
      mFile << "BBTK_USER_BLACK_BOX_TEMPLATE_IMPLEMENTATION("
	    << mName << ","  
	    << mParentBlackBox << ");\n";
     
      if (mGeneric) 
	{	
	  // Implementation
	  mFile << "BBTK_USER_BLACK_BOX_IMPLEMENTATION("
		<< mName << "Generic,bbtk::UserBlackBox);\n";
	  // Package
	  mFile << "BBTK_ADD_BLACK_BOX_TO_PACKAGE("
		<< mPackage << ","
		<< mName << "Generic)\n";
	}
    }
  else 
    {
      // Non template class
      // Package
      mFile << "BBTK_ADD_BLACK_BOX_TO_PACKAGE("
	    << mPackage << ","
	    << mName << ")\n";

      // Implementation
      mFile << "BBTK_USER_BLACK_BOX_IMPLEMENTATION("
	    << mName << ","  
	    << mParentBlackBox << ");\n";
 
      // Process
      if ((mType == STD)||(mProcess.size()))
	{
	  mFile << "void "<4) 
    {
      std::cerr << "usage : "<< argv[0] <<" xml_file [output_path] [-q]" << std::endl;
      return 1;
    }

  try 
    {
      std::string output_path("");
      bool verbose = true;
      if (argc>2) output_path = argv[2];
      if (argc>3) verbose = false;
      
      bbfy B(argv[1],output_path,verbose);
    }
  catch (bbfyException e)
    {
      std::cerr << e.mMessage << std::endl;
      return 1;
    }
  return 0;
}
//==========================================================================