cgma
RefEntityName.cpp
Go to the documentation of this file.
00001 #include "RefEntityName.hpp"
00002 #include "CubitString.hpp"
00003 #include "RefEntity.hpp"
00004 #include "CubitMessage.hpp"
00005 #include "CubitUtil.hpp"
00006 #include "CastTo.hpp"
00007 #include "RefGroup.hpp"
00008 #include "CubitAttribUser.hpp"
00009 #include "CADefines.hpp"
00010 #include <algorithm>
00011 
00012 #include "SettingHandler.hpp"
00013 
00014 #include <ctype.h>
00015 #include <assert.h>
00016 
00017 // template needed to sort CubitStrings
00018 
00019 template <> struct DLIListSorter<CubitString>
00020 {
00021   bool operator()(const CubitString &a, const CubitString &b) { return a < b; }
00022 };
00023 
00024 
00025 RefEntityName* RefEntityName::instance_ = 0;
00026 CubitBoolean RefEntityName::mergeBaseNames = CUBIT_FALSE;
00027 int RefEntityName::generateDefaultNames = CUBIT_FALSE;
00028 int RefEntityName::fixDuplicateNames = CUBIT_TRUE;
00029 char RefEntityName::suffixCharacter = '@';
00030 char RefEntityName::replacementCharacter = '_';
00031 static int is_valid_char(char c);
00032 static int is_valid_first_char(char c);
00033 bool RefEntityName::printNameChangeWarnings = true;
00034 int RefEntityName::numNameChangeWarnings = 0;
00035  
00036 RefEntityName* RefEntityName::instance()
00037 {
00038   if (instance_ == 0) {
00039     instance_ = new RefEntityName;
00040   }
00041   return instance_;
00042 }
00043 
00044 RefEntityName::RefEntityName()
00045 {
00046   generateDefaultNames = CUBIT_FALSE;
00047   fixDuplicateNames = CUBIT_TRUE;
00048   replacementCharacter = '_';
00049   suffixCharacter = '@';
00050 }
00051 
00052 RefEntityName::~RefEntityName()
00053 {
00054   instance_ = 0;
00055 }
00056 
00057 void RefEntityName::remove_refentity_name(RefEntity* entity,
00058                                           const CubitString &name,
00059                                           CubitBoolean update_attribs)
00060 {
00061   std::pair<RefEntityNameMap::iterator, RefEntityNameMap::iterator> iters = nameEntityList.refMap.equal_range(entity);
00062   std::map<CubitString, RefEntity*>::iterator jter = nameEntityList.nameMap.find(name);
00063 
00064   bool changed = false;
00065   for(;iters.first != iters.second; ++iters.first)
00066   {
00067     if(iters.first->second == name)
00068     {
00069       changed = true;
00070       nameEntityList.refMap.erase(iters.first);
00071       break;
00072     }
00073   }
00074   
00075   if( nameEntityList.nameMap.end() != jter && jter->second == entity)
00076   {
00077     changed = true;
00078     nameEntityList.nameMap.erase(jter);    
00079   }  
00080 
00081     // tell the ref entity to update its names
00082   if (changed && update_attribs)
00083   {
00084     CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME);
00085     attrib->has_updated(CUBIT_FALSE);
00086     attrib->update();
00087     if( attrib->delete_attrib() )
00088       entity->remove_cubit_attrib( attrib );
00089   }
00090 }
00091 
00092 void RefEntityName::remove_refentity_name(RefEntity *entity,
00093                                           CubitBoolean update_attribs)
00094 {
00095   //update the attribute so the names are put into the entity list
00096   if (update_attribs)
00097   {
00098     CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME,
00099                                                    CUBIT_FALSE);
00100     if (attrib) 
00101     {
00102       //update the attribute so that the names are on it.
00103       attrib->has_written( CUBIT_FALSE );
00104       attrib->has_updated(CUBIT_FALSE);
00105       attrib->update();
00106 
00107       //remove the attribute from the underlying entity
00108       //of the solid modeling kernel
00109       RefEntity *attrib_owner = attrib->attrib_owner();
00110       attrib_owner->remove_attrib_geometry_entity( attrib );
00111     }
00112   }
00113 
00114     // NOTE: There may be multiple names for one RefEntity. Make sure to 
00115     //       remove all of them. 
00116   
00117   std::pair<RefEntityNameMap::iterator, RefEntityNameMap::iterator> iters = nameEntityList.refMap.equal_range(entity);
00118 
00119   for(; iters.first != iters.second;)
00120   {
00121     CubitString name = iters.first->second;
00122 
00123     std::map<CubitString, RefEntity*>::iterator jter = nameEntityList.nameMap.find( name );
00124 
00125     if(nameEntityList.nameMap.end() != jter && jter->second == entity)
00126     {
00127       nameEntityList.nameMap.erase(jter);
00128     }
00129 
00130     nameEntityList.refMap.erase(iters.first++);
00131   }
00132 
00133     // now tell the entity to update its name attribute
00134   if (update_attribs)
00135   {
00136     CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME,
00137                                                    CUBIT_FALSE);
00138     if (attrib) 
00139     {
00140       attrib->has_updated(CUBIT_FALSE);
00141       attrib->update();
00142       entity->remove_cubit_attrib( attrib );
00143       delete attrib;
00144     }
00145   }
00146 }
00147 
00148 CubitStatus RefEntityName::add_refentity_name(RefEntity *entity,
00149                                               DLIList<CubitString> &names,
00150                                               bool update_attribs, 
00151                                               bool check_name_validity)
00152 {
00153   names.reset();
00154   //int num_new_names = names.size();
00155 
00156   DLIList<CubitString> new_names;
00157   
00158   for (int i=0; i<names.size(); i++)
00159   {
00160     CubitString name = names[i];
00161     CubitString in_name = name;
00162     CubitBoolean warn_name_change = CUBIT_FALSE;
00163     
00164       // first, clean the name
00165     if (check_name_validity)
00166     {
00167       if (clean(name))
00168       {
00169         // assign original name anyway, then
00170         // continue on and assign modified name.
00171         add_refentity_name(entity, in_name, false, false);
00172         warn_name_change = CUBIT_TRUE;
00173       }
00174     }
00175       // now, check for valid name
00176     CubitBoolean name_valid = CUBIT_FALSE;
00177 
00178     std::map<CubitString, RefEntity*>::iterator jter;
00179     jter = nameEntityList.nameMap.find( name );    
00180     bool name_exist = nameEntityList.nameMap.end() != jter;
00181     
00182     if (name == "")
00183     {
00184         // blank name entered - do nothing
00185     }
00186     
00187     else if( name_exist && jter->second == entity )
00188     {
00189         // Tried to assign same name to entity
00190       if ( DEBUG_FLAG(92) ) 
00191       {
00192           // check to see if it's the same as this entity's default name,
00193           // if so, it probably came in on an attribute, and we don't need
00194           // to hear about it; otherwise, write the warning
00195         CubitString def_name;
00196         entity->generate_default_name(def_name);
00197         if (name != def_name)
00198           PRINT_INFO("Entity name '%s' already assigned to %s %d\n",
00199                      name.c_str(), 
00200                      entity->class_name(), entity->id());
00201       }
00202     }
00203     else if(name_exist)
00204     {
00205         // Tried to assign existing name to another entity
00206       PRINT_DEBUG_92( "Entity name '%s' for %s %d is already used by %s %d\n",
00207                   name.c_str(), entity->class_name(), entity->id(),
00208                   jter->second->class_name(),
00209                   jter->second->id());
00210       
00211         // either we fix it and keep it, or we don't and get rid of it
00212       name_valid = CUBIT_FALSE;
00213       if (get_fix_duplicate_names())
00214       {
00215         //if the entity already has the base name, don't generate another
00216         DLIList<CubitString> tmp_names;
00217         get_refentity_name( entity, tmp_names );
00218         bool gen_unique_name = true;
00219         for( int k=0; k<tmp_names.size(); k++ )
00220         {
00221           CubitString tmp_name = tmp_names[k];
00222           if( same_base_name( name, tmp_name ) )
00223           {
00224             gen_unique_name = false;
00225             break;
00226           }
00227         }
00228 
00229         if (gen_unique_name && generate_unique_name(name) )
00230         {
00231           PRINT_DEBUG_92( "\t%s %d name changed to '%s'\n",
00232                           entity->class_name(), entity->id(), name.c_str());
00233           if(warn_name_change)
00234           {
00235             numNameChangeWarnings++;
00236             if(printNameChangeWarnings)
00237             {
00238               PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
00239                    "         Additional name '%s' assigned.\n",
00240                 in_name.c_str(), name.c_str());
00241             }
00242           }
00243           
00244           name_valid = CUBIT_TRUE;
00245         }
00246       }
00247     }
00248     else
00249     {
00250       if(warn_name_change)
00251       {
00252         numNameChangeWarnings++;
00253         if(printNameChangeWarnings)
00254         {
00255           PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
00256             "         Additional name '%s' assigned.\n",
00257             in_name.c_str(), name.c_str());
00258         }
00259       }
00260       
00261         // else the name must be valid
00262       name_valid = CUBIT_TRUE;
00263     }
00264     
00265     if (name_valid == CUBIT_TRUE)
00266     {
00267         // name is valid
00268       if (name != in_name)
00269           // name was changed; change in name list too
00270         names[i] = name;
00271 
00272         // save this name to later
00273       new_names.append(names[i]);
00274     }
00275   }
00276   
00277   if (new_names.size() > 0)
00278   {
00279       // there are some valid, new names; add them, then update attribute
00280     new_names.reset();
00281     
00282     for (int i = new_names.size(); i > 0; i--)
00283     {
00284       CubitString name = new_names.get_and_step();
00285       
00286       std::map<CubitString, RefEntity*>::iterator jter;
00287       jter = nameEntityList.nameMap.find( name );    
00288 
00289       if( nameEntityList.nameMap.end() != jter && jter->second == entity )
00290       {
00291             PRINT_DEBUG_92("Already have name %s for %s %d.\n",
00292                            name.c_str(), entity->class_name(), entity->id());
00293       }
00294       else
00295       {
00296         nameEntityList.nameMap.insert(std::make_pair(name, entity));
00297         nameEntityList.refMap.insert(std::make_pair(entity, name));
00298       }
00299     }
00300     
00301     if (update_attribs == CUBIT_TRUE)
00302     {
00303         // now tell the entity to update its name attribute
00304       CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME);
00305         // force update by resetting update flag
00306       attrib->has_updated(CUBIT_FALSE);
00307       attrib->update();
00308     }
00309   }
00310   
00311   return CUBIT_SUCCESS;
00312 }
00313 
00314 CubitStatus RefEntityName::add_refentity_name(RefEntity *entity,
00315                                               CubitString &name,
00316                                               bool update_attribs,
00317                                               bool check_name_validity)
00318 {
00319   if (name == "")
00320     return CUBIT_FAILURE;
00321   
00322   CubitString in_name = name;
00323   bool warn_name_change = false;
00324   
00325   if (check_name_validity)
00326   {
00327     if (clean(name))
00328     {
00329       // Assign the invalid name anyway, then continue on and
00330       // assign the modified name.
00331       add_refentity_name(entity, in_name, false, false);
00332       warn_name_change = true;
00333     }
00334   }
00335   
00336   std::map<CubitString, RefEntity*>::iterator jter;
00337   jter = nameEntityList.nameMap.find( name );
00338 
00339   if(nameEntityList.nameMap.end() != jter && jter->second == entity )
00340   {
00341       // Tried to assign same name to entity
00342     if ( DEBUG_FLAG(92) )
00343     {
00344       PRINT_INFO("Entity name '%s' already assigned to %s %d\n",
00345                  name.c_str(),
00346                  entity->class_name(), entity->id());
00347       return CUBIT_FAILURE;
00348     }
00349     return CUBIT_SUCCESS;
00350   }
00351   else if(nameEntityList.nameMap.end() != jter)
00352   {
00353       // Tried to assign existing name to another entity
00354     if ( DEBUG_FLAG(92) )
00355       PRINT_WARNING("Entity name '%s' for %s %d is already used by %s %d\n",
00356                     name.c_str(),
00357                     entity->class_name(), entity->id(),
00358                     jter->second->class_name(), jter->second->id());
00359     if (get_fix_duplicate_names())
00360     {
00361       //if the entity already has the base name, don't generate another
00362       DLIList<CubitString> tmp_names;
00363       get_refentity_name( entity, tmp_names );
00364       bool gen_unique_name = true;
00365       for( int k=0; k<tmp_names.size(); k++ )
00366       {
00367         CubitString tmp_name = tmp_names[k];
00368         if( same_base_name( name, tmp_name ) )
00369         {
00370           gen_unique_name = false;
00371           break;
00372         }
00373       }
00374 
00375       if (gen_unique_name && generate_unique_name(name))
00376       {
00377         if (warn_name_change)
00378         {
00379           numNameChangeWarnings++;
00380           if(printNameChangeWarnings)
00381           {
00382             PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
00383                  "         Additional name '%s' assigned.\n",
00384               in_name.c_str(), name.c_str());
00385           }
00386         }
00387         if ( DEBUG_FLAG(92) )
00388           PRINT_WARNING("\t%s %d name changed to '%s'\n",
00389           entity->class_name(), entity->id(), name.c_str());
00390         return add_refentity_name(entity, name, update_attribs, false);
00391       }
00392     }
00393     return CUBIT_FAILURE;
00394   }
00395 
00396   if (warn_name_change)
00397   {
00398     numNameChangeWarnings++;
00399     if(printNameChangeWarnings)
00400     {
00401       PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
00402         "         Additional name '%s' assigned.\n",
00403         in_name.c_str(), name.c_str());
00404     }
00405   }
00406 
00407   nameEntityList.nameMap.insert(std::make_pair(name, entity));
00408   nameEntityList.refMap.insert(std::make_pair(entity, name));
00409   
00410   if (update_attribs == CUBIT_TRUE)
00411   {
00412       // now tell the entity to update its name attribute
00413     CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME);
00414       // force update by resetting update flag
00415     attrib->has_updated(CUBIT_FALSE);
00416     attrib->update();
00417   }
00418   
00419   return CUBIT_SUCCESS;
00420 }
00421 
00422 int RefEntityName::get_refentity_name(const RefEntity *entity,
00423                                       DLIList<CubitString> &names)
00424 {
00425     // NOTE: There may be multiple names for one RefEntity. Make sure to 
00426     //       access all of them. 
00427 
00428   int num_names = 0;
00429   std::pair<RefEntityNameMap::iterator, RefEntityNameMap::iterator> iters = nameEntityList.refMap.equal_range(const_cast<RefEntity*>(entity));
00430   for(; iters.first != iters.second; ++iters.first)
00431   {
00432     num_names++;
00433     names.append(iters.first->second);
00434   }
00435 
00436   return num_names;
00437 }
00438 
00439 RefEntity*  RefEntityName::get_refentity(const CubitString &name) 
00440 {
00441   NameRefEntityMap::iterator iter = nameEntityList.nameMap.find(name);
00442   if (iter != nameEntityList.nameMap.end())
00443   {
00444     return iter->second;
00445   }
00446   return NULL;
00447 }
00448 
00449 const char* RefEntityName::get_refentity_type(const CubitString &name)
00450 {
00451   RefEntity *entity = get_refentity(name);
00452   if (entity != NULL) {
00453     return entity->class_name();
00454   } else {
00455     return NULL;
00456   }
00457 }
00458 
00459 int RefEntityName::get_refentity_id(const CubitString &name)
00460 {
00461   RefEntity *entity = get_refentity(name);
00462   if (entity != NULL) {
00463     return entity->id();
00464   } else {
00465     return 0;
00466   }
00467 }
00468 
00469 void RefEntityName::merge_refentity_names(RefEntity *retained,
00470                                           RefEntity *dead)
00471 {
00472   // NOTE: There may be multiple names for one RefEntity. Make sure to 
00473   //       process all of them.
00474 
00475   std::pair<RefEntityNameMap::iterator, RefEntityNameMap::iterator> iters = nameEntityList.refMap.equal_range(dead);
00476   if(iters.first == iters.second)
00477     return;
00478 
00479   std::pair<RefEntityNameMap::iterator, RefEntityNameMap::iterator> jters = nameEntityList.refMap.equal_range(retained);
00480 
00481   DLIList<CubitString> combined_names;
00482   for(RefEntityNameMap::iterator iter = jters.first; iter != jters.second; ++iter)
00483   {
00484     combined_names.append(iter->second);
00485   }
00486   for(RefEntityNameMap::iterator iter = iters.first; iter != iters.second; ++iter)
00487   {
00488     combined_names.append(iter->second);
00489   }
00490   combined_names.sort();
00491 
00492   remove_refentity_name(retained, false);
00493   remove_refentity_name(dead);
00494 
00495   if (get_merge_base_names() == CUBIT_TRUE)
00496   {
00497       // remove names with identical base names, keeping lowest
00498     for(int i=1; i<combined_names.size(); i++)
00499     {
00500       if(same_base_name(combined_names[i-1], combined_names[i]))
00501       {
00502         combined_names.remove();
00503 
00504       }
00505       combined_names.step();
00506     }
00507   }
00508 
00509   for(int i=0; i<combined_names.size(); i++)
00510   {
00511     nameEntityList.nameMap.insert(std::make_pair(combined_names[i], retained));
00512     nameEntityList.refMap.insert(std::make_pair(retained, combined_names[i]));
00513   }
00514 
00515     // now tell the entity to update its name attribute
00516   CubitAttrib *attrib = retained->get_cubit_attrib(CA_ENTITY_NAME);
00517     // force update by resetting update flag
00518   attrib->has_updated(CUBIT_FALSE);
00519   attrib->update();
00520 }
00521 
00522 void RefEntityName::switch_refentity_names(RefEntity *entity1,
00523                                            RefEntity *entity2)
00524 {
00525   // NOTE: There may be multiple names for one RefEntity. Make sure to 
00526   //       process all of them. 
00527 
00528   DLIList<CubitString> names1, names2;
00529   get_refentity_name(entity1, names1);
00530   get_refentity_name(entity2, names2);
00531 
00532   remove_refentity_name(entity1, false);
00533   remove_refentity_name(entity2, false);
00534 
00535   add_refentity_name(entity1, names2, true, false);
00536   add_refentity_name(entity2, names1, true, false);
00537 }
00538 
00539 void RefEntityName::list_refentity_names(const char *type)
00540 {
00541      // 'type' is a lowercase string specifying the type of entity to be
00542      // returned. (surface, body, ...)
00543      // if 'type' == "all", then all names will be listed.
00544    
00545    int do_all = (strcmp("all", type) == 0 || strlen(type) == 0);
00546    
00547    PRINT_INFO("\t______Name______  \t__Type__ Id\t\t_Propagated_\n");
00548    RefEntity *entity;
00549 
00550    for(NameRefEntityMap::iterator iter = nameEntityList.nameMap.begin(); iter != nameEntityList.nameMap.end(); ++iter)
00551     {
00552        entity = iter->second;
00553        if (do_all || CubitUtil::strcmp_case_insensitive(entity->class_name(),
00554                                                      type) == 0)
00555     {
00556        PRINT_INFO("%24s  %8s\t%-10d \tNo\n", iter->first.c_str(),
00557                   entity->class_name(), entity->id());
00558        }
00559     }
00560 }
00561 
00562 int RefEntityName::get_generate_default_names()
00563 {
00564   return generateDefaultNames;
00565 }
00566 
00567 void RefEntityName::set_generate_default_names(int on_off)
00568 {
00569   generateDefaultNames = on_off;
00570 }
00571 
00572 int RefEntityName::get_fix_duplicate_names()
00573 {
00574   return fixDuplicateNames;
00575 }
00576 
00577 void RefEntityName::set_fix_duplicate_names(int on_off)
00578 {
00579   fixDuplicateNames = on_off;
00580 }
00581 
00582 CubitStatus RefEntityName::clean(CubitString &raw_name)
00583 {
00584   if (raw_name == "")
00585     return CUBIT_FAILURE;
00586 
00587     // A valid name consists of alphanumeric characters plus '.', '_', '-', or '@'
00588   CubitStatus found_invalid_character = CUBIT_FAILURE;
00589 
00590   // Initial character must be alphabetic or "_".
00591   char c = raw_name.get_at(0);
00592   if (!is_valid_first_char(c)) {
00593     if (is_valid_first_char(get_character("replace")))
00594       raw_name.put_at(0, get_character("replace"));
00595     else
00596       raw_name.put_at(0, '_');
00597     found_invalid_character = CUBIT_SUCCESS;
00598   }
00599   
00600   for (unsigned int i = 1; i < raw_name.length(); i++) {
00601     c = raw_name.get_at(i);
00602     if (!is_valid_char(c)) {
00603       found_invalid_character = CUBIT_SUCCESS;
00604       raw_name.put_at(i, get_character("replace"));
00605     }
00606   }
00607   return found_invalid_character;
00608 }
00609 
00610 void RefEntityName::set_character(char rep, const CubitString &type)
00611 {
00612   if (is_valid_char(rep)) {
00613     if (type.get_at(0) == 'R' || type.get_at(0) == 'r')
00614       replacementCharacter = rep;
00615     else if (type.get_at(0) == 'S' || type.get_at(0) == 's')
00616       suffixCharacter = rep;
00617     else
00618       PRINT_ERROR("Invalid character type '%s', must be "
00619           "'replacement' or 'suffix'\n", type.c_str());
00620   } else {
00621     PRINT_ERROR("Character '%c' is not a valid entity name character\n",
00622         rep);
00623   }
00624 }
00625 
00626 char RefEntityName::get_character(const CubitString& type) const
00627 {
00628   if (type.get_at(0) == 'R' || type.get_at(0) == 'r')
00629     return replacementCharacter;
00630   else if (type.get_at(0) == 'S' || type.get_at(0) == 's')
00631     return suffixCharacter;  
00632   else {
00633     PRINT_ERROR("Invalid character type '%s', must be "
00634         "'replacement' or 'suffix'\n", type.c_str());
00635     return '#';
00636   }
00637 }
00638 
00639 static int is_valid_char(char c)
00640 {
00641   return (!isascii(c) || isalnum(c) || c == '.' || c == '_' || c == '@');
00642 }
00643 
00644 static int is_valid_first_char(char c)
00645 {
00646   return (!isascii(c) || isalpha(c) || c == '_');
00647 }
00648 
00649 CubitStatus RefEntityName::generate_unique_name(CubitString &name )
00650 {
00651   // The method used to generate a unique name is to append
00652   // 'suffixCharacter' and
00653   // a letter from A-Z, a-z, or 0-9 to the end of name.
00654   // If none of these produce a unique name, CUBIT_FALSE is returned.
00655 
00656   CubitString alphabet =
00657     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
00658   CubitString suffix("  ");
00659   suffix.put_at(0, suffixCharacter);
00660   
00661   CubitString internal = name;
00662 
00663   // See if there is an suffixCharacter sign in name already. If so, is it
00664   // the second to the last character in the string.
00665   if (name.length() < 2 ||
00666       name.get_at(name.length()-2) != suffixCharacter) {
00667     // Name does not contain suffixCharacter at correct location, add one on.
00668     internal += suffix;
00669   }
00670   
00671   CubitStatus found_unique = CUBIT_FAILURE;
00672   int continue_trying = CUBIT_TRUE;
00673 
00674   while (!found_unique && continue_trying) {
00675 
00676     continue_trying = CUBIT_FALSE;
00677     int name_length = internal.length();
00678     unsigned int number_tested = 0;
00679     for (unsigned int i=0; i < alphabet.length(); i++) {
00680       internal.put_at(name_length-1, (char)alphabet.get_at(i));
00681       if (nameEntityList.nameMap.find(internal) == nameEntityList.nameMap.end())
00682       {
00683         found_unique = CUBIT_SUCCESS;
00684         break;
00685       }
00686       number_tested++;
00687     }
00688 
00689     if (number_tested == alphabet.length()) {
00690       // All suffixes used. Add another suffixCharacter and try again
00691       // Name will look like 'Name@@1' or 'Name@@@1'...
00692       // Find LAST suffixCharacter in name
00693       int ch;
00694       for (ch = (int)(internal.length())-1; ch >= 0; ch--) {
00695         if (internal.get_at(ch) == suffixCharacter) {
00696           break;
00697         }
00698       }
00699       if (internal.get_at(ch) == suffixCharacter) {
00700         // Add another suffixCharacter at ch+1
00701         // Assured that position ch+1 exists or we wouldn't be here
00702         internal.put_at(ch+1, suffixCharacter);
00703         if (ch+2 < (int)internal.length())
00704           internal.put_at(ch+2, ' ');
00705         else
00706           internal += " ";
00707         continue_trying = CUBIT_TRUE;
00708       }
00709     }
00710   }
00711   
00712   if (found_unique)
00713     name = internal;
00714 
00715   return found_unique;
00716 }
00717 
00718 CubitString RefEntityName::base_name(const CubitString& name)
00719 {
00720   const char *pos = strchr(name.c_str(), suffixCharacter);
00721   if (!pos)
00722     return name;
00723   return name.substr(0, pos - name.c_str());
00724 }
00725 
00726 
00727 // returns CUBIT_TRUE if the two names have the same base name (i.e.
00728 // the same name before the first suffixCharacter
00729 CubitBoolean RefEntityName::same_base_name(const CubitString &name1,
00730                                            const CubitString &name2)
00731 {
00732   const char *pos1 = strchr(name1.c_str(), suffixCharacter);
00733   const char *pos2 = strchr(name2.c_str(), suffixCharacter);
00734 
00735     // check for replacement character in one but not the other
00736   int length1, length2;
00737   if (pos1 == NULL)
00738     length1 = strlen(name1.c_str());
00739   else
00740     length1 = pos1 - name1.c_str();
00741 
00742   if (pos2 == NULL)
00743     length2 = strlen(name2.c_str());
00744   else
00745     length2 = pos2 - name2.c_str();
00746 
00747     // if the lengths are different, the base names are also different
00748   if (length1 != length2)
00749     return CUBIT_FALSE;
00750 
00751   if (strncmp(name1.c_str(), name2.c_str(), length1) == 0)
00752     return CUBIT_TRUE;
00753   else
00754     return CUBIT_FALSE;
00755 }
00756 
00757 // Copy names from one entity to another.  
00758 // Added Aug.14,2000 by J.Kraftcheck for propogating
00759 // names after virtual geometry operations.
00760 void RefEntityName::copy_refentity_names( const RefEntity *source,
00761                                           RefEntity *target,
00762                                           CubitBoolean update_attribs )
00763 {
00764   //No NULL pointers.
00765   assert( source && target );
00766   
00767   //If we can't have duplicate names, then it is not possible to 
00768   //copy names.
00769   if( ! get_fix_duplicate_names() ) return;
00770   
00771   //Assume the name is valid already, as it is attached to
00772   //the source entity.  Also, assume the name is unique to
00773   //the source entity.
00774   DLIList<CubitString> names;
00775   get_refentity_name( source, names );
00776   names.reset();
00777   
00778   //For each of the names on the source entity
00779   for( int i = names.size(); i > 0; i-- )
00780   {  
00781     CubitString name = names.get_and_step();
00782     //make the name unique
00783     generate_unique_name( name );
00784     //associate name with target
00785 
00786     nameEntityList.nameMap.insert( std::make_pair( name, target ) );
00787     nameEntityList.refMap.insert( std::make_pair( target, name ) );
00788   }
00789     
00790   if( (names.size() > 0) && (update_attribs == CUBIT_TRUE) )
00791   {
00792       // now tell the entity to update its name attribute
00793     CubitAttrib *attrib = target->get_cubit_attrib( CA_ENTITY_NAME );
00794       // force update by resetting update flag
00795     attrib->has_updated( CUBIT_FALSE );
00796     attrib->update();
00797   }
00798 }
00799 
00800 
00801 
00802 //Initialize all settings in this class
00803 void RefEntityName::initialize_settings()
00804 {
00805 
00806   SettingHandler::instance()->add_setting("Default Names", 
00807                                           RefEntityName::set_generate_default_names, 
00808                       RefEntityName::get_generate_default_names); 
00809 
00810   SettingHandler::instance()->add_setting("Fix Duplicate Names", 
00811                                           RefEntityName::set_fix_duplicate_names, 
00812                       RefEntityName::get_fix_duplicate_names);
00813    
00814   SettingHandler::instance()->add_setting("Replacement Character", 
00815                       RefEntityName::set_replacement_setting, 
00816                       RefEntityName::get_replacement_setting);  
00817 
00818   SettingHandler::instance()->add_setting("Suffix Character",
00819                       RefEntityName::set_suffix_setting,
00820                       RefEntityName::get_suffix_setting);
00821 
00822   SettingHandler::instance()->add_setting("Merge Base Names", 
00823                                           RefEntityName::set_merge_base_names, 
00824                       RefEntityName::get_merge_base_names); 
00825 
00826 }
00827 
00828 
00829 void RefEntityName::copy_refentity_names( DLIList<RefEntity*>& source_list,
00830                                           RefEntity* target,
00831                                           CubitBoolean unique_base_names,
00832                                           CubitBoolean update_attribs )
00833 {
00834   //Validate input.
00835   assert( target != 0 );
00836   if( source_list.size() < 1 ) return;
00837   
00838   //If we can't have duplicate names, we can't copy.
00839   if( ! get_fix_duplicate_names() ) return;
00840   
00841   //If we need to ensure no duplicate base names...
00842   if( unique_base_names )
00843   {
00844     //Get a big list of all the names from the source_list
00845     DLIList<CubitString> name_list;
00846     source_list.reset();
00847     for( int i = source_list.size(); i > 0; i-- )
00848       get_refentity_name( source_list.get_and_step(), name_list );
00849       
00850     //If we don't have any names to add, we're done
00851     if( name_list.size() < 1 ) return;
00852     
00853     //Get the first name
00854     name_list.sort();
00855     name_list.reset();
00856     CubitString prev_key = name_list.get_and_step();
00857     
00858     //Add name to target
00859     CubitString name = prev_key;
00860     generate_unique_name( name );
00861     nameEntityList.nameMap.insert( std::make_pair( name, target ) );
00862     nameEntityList.refMap.insert( std::make_pair( target, name ) );
00863   
00864     //For the rest of the names...
00865     for( int j = name_list.size(); j > 1; j-- )
00866     {
00867       CubitString key_ptr = name_list.get_and_step();
00868       
00869       //If the name has a different base name than the previous, 
00870       //add it to the target.
00871       if( !same_base_name( prev_key, key_ptr ) )
00872       {
00873         name = key_ptr;
00874         generate_unique_name( name );
00875         nameEntityList.nameMap.insert( std::make_pair( name, target ) );
00876         nameEntityList.refMap.insert( std::make_pair( target, name ) );
00877       }
00878        
00879       prev_key = key_ptr;
00880     }
00881   
00882     //update attribute, if asked to do so
00883     if( update_attribs  )
00884     {
00885       CubitAttrib *attrib = target->get_cubit_attrib( CA_ENTITY_NAME );
00886       attrib->has_updated( CUBIT_FALSE );
00887       attrib->update();
00888     }
00889     
00890   }
00891   else
00892   {
00893     //If we don't care about unique base names, just add them all.
00894     DLIList<CubitString> name_list;
00895     for( int i = source_list.size(); i > 0; i-- )
00896       get_refentity_name( source_list.get_and_step(), name_list );
00897     name_list.reset();
00898     add_refentity_name(target, name_list, update_attribs, false);
00899   }
00900 }
00901 
00902 
00903 
00904 void RefEntityName::set_suffix_setting(CubitString rep)
00905 {
00906   const char* tmp = rep.c_str();
00907   suffixCharacter = tmp[0];
00908 }
00909 
00910 CubitString RefEntityName::get_suffix_setting()
00911 {
00912   char tmp[] = {suffixCharacter, '\0'};
00913   return CubitString(tmp);
00914 }
00915 
00916 void RefEntityName::set_replacement_setting(CubitString rep)
00917 {
00918   const char* tmp = rep.c_str();
00919   replacementCharacter = tmp[0];
00920 }
00921 
00922 CubitString RefEntityName::get_replacement_setting()
00923 {
00924   char tmp[] = {replacementCharacter, '\0'};
00925   return CubitString(tmp);
00926 }
00927 
00928 
00929 
00930 
00931 
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939 
00940 
00941 
00942 
00943 
00944 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines