+//================================================================================
+/*!
+ * \brief Return paths to xml files of plugins
+ */
+//================================================================================
+
+std::vector< std::string > SMESH_Gen::GetPluginXMLPaths()
+{
+ // Get paths to xml files of plugins
+ vector< string > xmlPaths;
+ string sep;
+ if ( const char* meshersList = getenv("SMESH_MeshersList") )
+ {
+ string meshers = meshersList, plugin;
+ string::size_type from = 0, pos;
+ while ( from < meshers.size() )
+ {
+ // cut off plugin name
+ pos = meshers.find( ':', from );
+ if ( pos != string::npos )
+ plugin = meshers.substr( from, pos-from );
+ else
+ plugin = meshers.substr( from ), pos = meshers.size();
+ from = pos + 1;
+
+ // get PLUGIN_ROOT_DIR path
+ string rootDirVar, pluginSubDir = plugin;
+ if ( plugin == "StdMeshers" )
+ rootDirVar = "SMESH", pluginSubDir = "smesh";
+ else
+ for ( pos = 0; pos < plugin.size(); ++pos )
+ rootDirVar += toupper( plugin[pos] );
+ rootDirVar += "_ROOT_DIR";
+
+ const char* rootDir = getenv( rootDirVar.c_str() );
+ if ( !rootDir || strlen(rootDir) == 0 )
+ {
+ rootDirVar = plugin + "_ROOT_DIR"; // HexoticPLUGIN_ROOT_DIR
+ rootDir = getenv( rootDirVar.c_str() );
+ if ( !rootDir || strlen(rootDir) == 0 ) continue;
+ }
+
+ // get a separator from rootDir
+ for ( pos = strlen( rootDir )-1; pos >= 0 && sep.empty(); --pos )
+ if ( rootDir[pos] == '/' || rootDir[pos] == '\\' )
+ {
+ sep = rootDir[pos];
+ break;
+ }
+#ifdef WNT
+ if (sep.empty() ) sep = "\\";
+#else
+ if (sep.empty() ) sep = "/";
+#endif
+
+ // get a path to resource file
+ string xmlPath = rootDir;
+ if ( xmlPath[ xmlPath.size()-1 ] != sep[0] )
+ xmlPath += sep;
+ xmlPath += "share" + sep + "salome" + sep + "resources" + sep;
+ for ( pos = 0; pos < pluginSubDir.size(); ++pos )
+ xmlPath += tolower( pluginSubDir[pos] );
+ xmlPath += sep + plugin + ".xml";
+ bool fileOK;
+#ifdef WNT
+ fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES);
+#else
+ fileOK = (access(xmlPath.c_str(), F_OK) == 0);
+#endif
+ if ( fileOK )
+ xmlPaths.push_back( xmlPath );
+ }
+ }
+
+ return xmlPaths;
+}
+
+//=======================================================================
+namespace // Access to type of input and output of an algorithm
+//=======================================================================
+{
+ struct AlgoData
+ {
+ int _dim;
+ set<SMDSAbs_GeometryType> _inElemTypes; // acceptable types of input mesh element
+ set<SMDSAbs_GeometryType> _outElemTypes; // produced types of mesh elements
+
+ bool IsCompatible( const AlgoData& algo2 ) const
+ {
+ if ( _dim > algo2._dim ) return algo2.IsCompatible( *this );
+ // algo2 is of highter dimension
+ if ( _outElemTypes.empty() || algo2._inElemTypes.empty() )
+ return false;
+ bool compatible = true;
+ set<SMDSAbs_GeometryType>::const_iterator myOutType = _outElemTypes.begin();
+ for ( ; myOutType != _outElemTypes.end() && compatible; ++myOutType )
+ compatible = algo2._inElemTypes.count( *myOutType );
+ return compatible;
+ }
+ };
+
+ //================================================================================
+ /*!
+ * \brief Return AlgoData of the algorithm
+ */
+ //================================================================================
+
+ const AlgoData& getAlgoData( const SMESH_Algo* algo )
+ {
+ static map< string, AlgoData > theDataByName;
+ if ( theDataByName.empty() )
+ {
+ // Read Plugin.xml files
+ vector< string > xmlPaths = SMESH_Gen::GetPluginXMLPaths();
+ LDOMParser xmlParser;
+ for ( size_t iXML = 0; iXML < xmlPaths.size(); ++iXML )
+ {
+ bool error = xmlParser.parse( xmlPaths[iXML].c_str() );
+ if ( error )
+ {
+ TCollection_AsciiString data;
+ INFOS( xmlParser.GetError(data) );
+ continue;
+ }
+ // <algorithm type="Regular_1D"
+ // ...
+ // input="EDGE"
+ // output="QUAD,TRIA">
+ //
+ LDOM_Document xmlDoc = xmlParser.getDocument();
+ LDOM_NodeList algoNodeList = xmlDoc.getElementsByTagName( "algorithm" );
+ for ( int i = 0; i < algoNodeList.getLength(); ++i )
+ {
+ LDOM_Node algoNode = algoNodeList.item( i );
+ LDOM_Element& algoElem = (LDOM_Element&) algoNode;
+ TCollection_AsciiString algoType = algoElem.getAttribute("type");
+ TCollection_AsciiString input = algoElem.getAttribute("input");
+ TCollection_AsciiString output = algoElem.getAttribute("output");
+ TCollection_AsciiString dim = algoElem.getAttribute("dim");
+ if ( algoType.IsEmpty() ) continue;
+ AlgoData & data = theDataByName[ algoType.ToCString() ];
+ data._dim = dim.IntegerValue();
+ for ( int isInput = 0; isInput < 2; ++isInput )
+ {
+ TCollection_AsciiString& typeStr = isInput ? input : output;
+ set<SMDSAbs_GeometryType>& typeSet = isInput ? data._inElemTypes : data._outElemTypes;
+ int beg = 1, end;
+ while ( beg <= typeStr.Length() )
+ {
+ while ( beg < typeStr.Length() && !isalpha( typeStr.Value( beg ) ))
+ ++beg;
+ end = beg;
+ while ( end < typeStr.Length() && isalpha( typeStr.Value( end + 1 ) ))
+ ++end;
+ if ( end > beg )
+ {
+ TCollection_AsciiString typeName = typeStr.SubString( beg, end );
+ if ( typeName == "EDGE" ) typeSet.insert( SMDSGeom_EDGE );
+ else if ( typeName == "TRIA" ) typeSet.insert( SMDSGeom_TRIANGLE );
+ else if ( typeName == "QUAD" ) typeSet.insert( SMDSGeom_QUADRANGLE );
+ }
+ beg = end + 1;
+ }
+ }
+ }
+ }
+ }
+ return theDataByName[ algo->GetName() ];
+ }
+}
+