// File:	TNaming_Naming.cxx
// Created:	Wed Sep  3 09:36:05 1997
// Author:	Yves FRICAUD
//		<yfr@claquox.paris1.matra-dtv.fr>
//Copyright:	 Matra Datavision 1997


#include <TNaming_Naming.ixx>

#include <TNaming_Builder.hxx>
#include <TNaming_Tool.hxx>
#include <TNaming_ListIteratorOfListOfNamedShape.hxx>
#include <TNaming_Iterator.hxx>
//
#include <TNaming_Scope.hxx>
#include <TNaming_NamingTool.hxx>
#include <TNaming_Name.hxx>
#include <TNaming_Identifier.hxx>
#include <TNaming_Localizer.hxx>
#include <TNaming_NewShapeIterator.hxx>
#include <TNaming_OldShapeIterator.hxx>
//
#include <TDF_ChildIterator.hxx>
#include <TDF_LabelList.hxx>
#include <TDF_Data.hxx>
#include <TDF_LabelMap.hxx>
#include <TDF_TagSource.hxx>
#include <TDF_MapIteratorOfLabelMap.hxx> 
#include <TopoDS_Iterator.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_MapIteratorOfMapOfShape.hxx>
#include <Standard_DomainError.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>

// The bug concerns access to a null object in the method Filter():
#define BUC60847

#define OCC273
#define OCC350
#define OCC352
#ifdef DEB
#include <TCollection_AsciiString.hxx>
#include <TDF_Tool.hxx>
#include <BRepTools.hxx>
#include <TNaming_Tool.hxx>

//unreferenced function, commented  
/*static void ModDbgTools_Write(const TopoDS_Shape& shape,
		      const Standard_CString filename) 
{
  ofstream save;
  save.open(filename);
  save << "DBRep_DrawableShape" << endl << endl;
  if(!shape.IsNull()) BRepTools::Write(shape, save);
  save.close();
}

static void ModDbgTools_WriteCurrentShape(const Handle(TNaming_NamedShape) & NS)
{
  TCollection_AsciiString entry;
  TDF_Tool::Entry(NS->Label(), entry);
  if (!NS.IsNull())
    {
      TopoDS_Shape Sh = TNaming_Tool::CurrentShape (NS);
      if(!Sh.IsNull()) {
	TCollection_AsciiString Entry = entry.Cat("_Cur.brep");
	ModDbgTools_Write(Sh, Entry.ToCString());
      }
      else 
	cout << "ModDbgTools::Write>>> TopoDS_Shape IS NULL on Entry = "<< entry << endl;
    }
  else
    cout << "ModDbgTools::Write>>>  CurrentShape of TNaming_NamedShape IS NULL on Entry = "<< entry << endl;
}*/
#endif
//==========================================================================================
static Handle(TNaming_NamedShape) BuildName (const  TDF_Label&   F,
					     TNaming_Scope&                    MDF,
					     const TopoDS_Shape&               S,
					     const TopoDS_Shape&               Context, 
					     const Handle(TNaming_NamedShape)& Stop,
					     const Standard_Boolean            Geometry);


//=======================================================================
//function : Solve
//purpose  : voir avec YFR comment retrouver le bon resulat et le mettre dans le NamedShape de L
//=======================================================================

Standard_Boolean  TNaming_Naming::Solve (TDF_LabelMap& Valid) 
{ 
  Handle(TNaming_Naming) subname;
  for (TDF_ChildIterator it (Label(),Standard_False); it.More(); it.Next()) {
    if (it.Value().FindAttribute(TNaming_Naming::GetID(),subname)) {
      if (!subname->Solve (Valid)) {
	return Standard_False; // not necessary to continue
      }
    }
  }
  if (Regenerate(Valid)) {
    if (!Valid.IsEmpty()) Valid.Add(Label());
    return Standard_True;
  }
  return Standard_False; 
}
 
 
//=======================================================================
//function : GetID
//purpose  : 
//=======================================================================

const Standard_GUID& TNaming_Naming::GetID () 
{
  static Standard_GUID TNaming_NamingID("c0a19201-5b78-11d1-8940-080009dc3333");
  return TNaming_NamingID; 
}

//=======================================================================
//function : Insert
//purpose  : 
//=======================================================================

Handle(TNaming_Naming) TNaming_Naming::Insert (const TDF_Label& under) 
{
  Handle(TNaming_Naming) N;  
  TDF_Label child = TDF_TagSource::NewChild(under);
  N = new TNaming_Naming ();  
  child.AddAttribute (N);
  return N;
}  
  
//=======================================================================
//function : BuildNS
//purpose  : 
//=======================================================================

static Handle(TNaming_NamedShape)  BuildNS (const TDF_Label&   F,
					    const TopoDS_Shape&               S,
					    const TNaming_NameType&           Name)
{
  Handle (TNaming_Naming) Naming = TNaming_Naming::Insert (F);
  
  TNaming_Name& theName = Naming->ChangeName();
  theName.ShapeType(S.ShapeType());
  theName.Shape(S); //szy_21.10.03
  theName.Type(Name);
  TNaming_Builder B(Naming->Label());
  B.Select(S,S);
  return B.NamedShape();
}

//=======================================================================
//function : FindIndex
//purpose  : 
//=======================================================================

static Standard_Integer FindIndex(const Handle(TNaming_NamedShape)& NS,
				  const TopoDS_Shape&               S)
{
  TDF_LabelList Labels;
  TopoDS_Shape IS = TNaming_Tool::InitialShape(S,NS->Label(),Labels);
  Standard_Integer Index = 1;
  for (TNaming_Iterator itNS(NS); itNS.More(); itNS.Next(),Index++) {
    if (IS.IsSame(itNS.NewShape())) break;
  }
  return Index;
}


//=======================================================================
//function : CompareInGeneration
//purpose  : 
//=======================================================================

static Standard_Boolean CompareInGeneration (const Handle(TNaming_NamedShape)& NS,
					     const TopoDS_Shape&               S)
{
  for (TNaming_Iterator it(NS); it.More(); it.Next()) {
    if (!it.NewShape().IsSame(S)) return 0;
  }
  return 1;
}

#ifdef OCC350

//=======================================================================
//function : GetShapeEvolutions
//purpose  : returns Standard_True, if target has parent in source; list contains inheritance chain
//=======================================================================
static Standard_Boolean GetShapeEvolutions(const TopoDS_Shape&               theTarget, // this is changed in recursion
					   const Handle(TNaming_NamedShape)& theSource,
					   TopTools_ListOfShape&         aList) // returns list in the backward order
{
  Handle(TNaming_NamedShape) aTarget = TNaming_Tool::NamedShape(theTarget,theSource->Label());
  if (!aTarget.IsNull()) {
    if (aTarget->Label() == theSource->Label()) return Standard_True; // check if target is in the source
  } else return Standard_False;

  TNaming_Iterator anIter(aTarget);
  for(;anIter.More();anIter.Next()) { // check all appropriate old shapes of target
    if (anIter.OldShape().IsNull() || anIter.NewShape().IsNull()) continue;
    if (!anIter.NewShape().IsSame(theTarget)) continue;
    if (GetShapeEvolutions(anIter.OldShape(),theSource,aList)) { // recursion: now target is old shape
      aList.Append(theTarget); // if oldshape has the source as parent (or belongs to it) , fill the list
      return Standard_True;
    }
  }
  return Standard_False;
}

//=======================================================================
//function : CompareInModification
//purpose  : returns empty named shape if naming is already done
//=======================================================================

static Handle(TNaming_NamedShape) CompareInModification (const Handle(TNaming_NamedShape)& NS, // parent
							 const TopoDS_Shape&               S)  // target
{
  Handle(TNaming_NamedShape) aResult;
  if (S.IsNull() || NS.IsNull()) return aResult;

  Handle(TNaming_NamedShape) aSource; // parent NamedShape, which can be found by TopoDS shape
  TNaming_Iterator anIt(NS);
  for(;anIt.More() && aSource.IsNull();anIt.Next()) {
    if (!anIt.NewShape().IsNull()) aSource = TNaming_Tool::NamedShape(anIt.NewShape(),NS->Label());
  }
  // searching for 1:n to the same label modifications (in this case current naming is insufficient)
  TopTools_ListOfShape aList;
  if (GetShapeEvolutions(S,aSource,aList) && aList.Extent() > 0) {
    TopTools_ListIteratorOfListOfShape anIter(aList);
    for(;anIter.More();anIter.Next()) {
      aResult = TNaming_Tool::NamedShape(anIter.Value(),NS->Label());
      if (aResult->Evolution()!=TNaming_MODIFY) { // evolution must be modify, otherwise everything is OK
	aResult.Nullify();
	return aResult;
      }
      TopTools_MapOfShape aMap; // collection of the old shapes of the shape from list
      TNaming_Iterator aNIter1(aResult);
      for(;aNIter1.More();aNIter1.Next()) {
	if (aNIter1.NewShape().IsSame(anIter.Value())) aMap.Add(aNIter1.OldShape());
      }
      TNaming_Iterator aNIter2(aResult); // if some another shapes has oldshape from map, return namedshape with this oldshape
      for(;aNIter2.More();aNIter2.Next()) {
	if (aNIter2.NewShape().IsSame(anIter.Value())) continue;
	if (aMap.Contains(aNIter2.OldShape())) { // if one shape was modified to the two at the shared label, return this one
	  aResult = TNaming_Tool::NamedShape(aNIter2.OldShape(),NS->Label());
	  if (!aResult.IsNull()) return aResult;
	}
      }
    }
    aResult.Nullify();
  }
  return aResult;
}
#endif


//=======================================================================
//function : Compare
//purpose  : 
//=======================================================================

static Standard_Boolean Compare (const Handle(TNaming_NamedShape)& NS,
				 const TNaming_Scope&      MDF,
				 const Handle(TNaming_NamedShape)& Stop,
				 const TopoDS_Shape&               S)
{
  TDF_LabelMap Forbiden;
  TopTools_MapOfShape MS;
  if (!Stop.IsNull()) TNaming_NamingTool::BuildDescendants(Stop,Forbiden);
  TNaming_NamingTool::CurrentShape(MDF.GetValid(),Forbiden,NS,MS);
  
  return (MS.Contains(S) && MS.Extent() == 1);
}
//=======================================================================
//function : TestSolution
//purpose  : 
//=======================================================================

static Standard_Boolean TestSolution(const TNaming_Scope&      MDF,
				     const Handle(TNaming_NamedShape)& NS,
				     const TopoDS_Shape&               S)
{ 

  if (NS.IsNull()) return Standard_False;
  TopoDS_Shape Res = MDF.CurrentShape(NS);
  
#ifdef OCC352

  if (S.ShapeType() == TopAbs_FACE  ||
      S.ShapeType() == TopAbs_EDGE  ||
      S.ShapeType() == TopAbs_VERTEX ) { 
    return (Res.IsSame(S));
  } else if (S.ShapeType() == TopAbs_SOLID ||
	S.ShapeType() == TopAbs_COMPSOLID) {
    TopTools_MapOfShape aMS;
    TopExp_Explorer exp;
    for (exp.Init(S,TopAbs_FACE) ; exp.More(); exp.Next()) {
      aMS.Add(exp.Current());
    }
    for (exp.Init(Res,TopAbs_FACE) ; exp.More(); exp.Next()) {
      if (aMS.Contains(exp.Current())) {
	aMS.Remove(exp.Current());
      }
      else return 0;
    }
    return aMS.IsEmpty();
  } else {

#else

  if (S.ShapeType() == TopAbs_SOLID ||
      S.ShapeType() == TopAbs_FACE  ||
      S.ShapeType() == TopAbs_EDGE  ||
      S.ShapeType() == TopAbs_VERTEX ) { 
    return (Res.IsSame(S));
  }
  else {

#endif

    TopTools_MapOfShape MS;
//    for (TopoDS_Iterator it(S) ; it.More(); it.Next()) {
    TopoDS_Iterator it;//(S);
    for (it.Initialize(S) ; it.More(); it.Next()) {
      MS.Add(it.Value());
    }

    if (MS.Contains(Res)) {
      MS.Remove(Res);
      if (MS.IsEmpty()) return 1;
    }

    for (it.Initialize(Res) ; it.More(); it.Next()) {
      if (MS.Contains(it.Value())) {
	MS.Remove(it.Value());
      }
      else return 0;
    }
    return MS.IsEmpty();
  }
}

//=======================================================================
//function : FindNewShapeInFather
//purpose  :
//=======================================================================

static void FindNewShapeInFather (const Handle(TNaming_NamedShape)& NS,
				  TopoDS_Shape&                     SC)
{  
  TDF_Label         Father  = NS->Label().Father(); 
  TNaming_Iterator  itLab(Father);
  for (; itLab.More(); itLab.Next()) {
    SC= itLab.NewShape();
    break;
  }
}

//=======================================================================
//function : NextModif
//purpose  : 
//=======================================================================

static Handle(TNaming_NamedShape) NextModif(const Handle(TNaming_NamedShape)& NS)
{
  Handle (TNaming_NamedShape) Next;
  if (!NS.IsNull()) {
    TNaming_NewShapeIterator it(NS); 
    if (it.More()&& it.IsModification()) Next = it.NamedShape();
  }
  return Next;
}

//=======================================================================
//function : Filter
//purpose  : 
//=======================================================================

static Standard_Boolean Filter (const TDF_Label&                  F,
				TNaming_Scope&               MDF,
				const TopoDS_Shape&               S,
				const TopoDS_Shape&               Context,
				TNaming_Localizer&                Localizer,
				Handle(TNaming_NamedShape)&       NS)
{ 
  //------------------------------
  // Construction des voisins.
  //------------------------------
  TopTools_MapOfShape Neighbourg;
  Localizer.FindNeighbourg (Context,S,Neighbourg);

#ifdef OCC273
  // mpv : NS and shape must be the same
  Standard_Boolean isIn = Standard_False;
  TNaming_Iterator anIter(NS);
  for(;anIter.More();anIter.Next()) {
    if (anIter.NewShape().IsSame(S)) {
      isIn = Standard_True;
      break;
    }
  }
  if (!isIn) if (!TNaming_Tool::NamedShape(S,F).IsNull()) NS = TNaming_Tool::NamedShape(S,F);
//  if (!TNaming_Tool::NamedShape(S,F).IsNull()) NS = TNaming_Tool::NamedShape(S,F);
#endif
  
  if (Neighbourg.IsEmpty()) {
    // Recherche du vrai context. 
    Handle(TNaming_NamedShape) GenS = TNaming_Tool::NamedShape(S,NS->Label());
#ifdef BUC60847
    if (GenS.IsNull()) return Standard_False;
#endif
    TDF_Label Father = (GenS->Label()).Father();
    Father.FindAttribute(TNaming_NamedShape::GetID(),GenS);
    TopoDS_Shape GoodContext = TNaming_Tool::GetShape(GenS);
    Localizer.FindNeighbourg (GoodContext,S,Neighbourg);
  }
  

  if (Neighbourg.IsEmpty()) {      
    cout <<"FindNeighbourg: impossible"<<endl;
    return 0;  
  }
  //-----------------------------------------------------
  // Construction function de naming. et insertion sous F
  //-----------------------------------------------------
  Handle (TNaming_Naming) NF = TNaming_Naming::Insert (F);
  
  Handle (TNaming_NamedShape) Until = TNaming_Tool::NamedShape(Context,NS->Label());
  Handle (TNaming_NamedShape) Stop  = NextModif(Until); 
  TNaming_Name& theName = NF->ChangeName();
  theName.ShapeType(S.ShapeType());
  theName.Shape(S); //szy_21.10.03
  theName.Type(TNaming_FILTERBYNEIGHBOURGS);
  theName.Append(NS);
  theName.StopNamedShape (Until);
  //---------------------
  // Naming des voisins.
  //---------------------
  TopTools_MapIteratorOfMapOfShape itN(Neighbourg);
  for (; itN.More(); itN.Next()) {

    theName.Append(BuildName(NF->Label(), MDF, itN.Key(), Context, Stop, 1));
  }
  //------------------------------
  // Compute the TNaming_NamedShape
  //------------------------------
  NF->Regenerate(MDF.ChangeValid());
  NF->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);

  //-----------------
  // Check du filtre.
  //-----------------
  if (Compare (NS,MDF,Stop,S)) return 1;  
#ifdef DEB
  cout <<"TNaming_Naming::Name Filter insufficient"<<endl;
#endif
  return 0;
}


//=======================================================================
//function : 
//purpose  : 
//=======================================================================
static Handle(TNaming_NamedShape) BuildNameInNS (const TDF_Label&                  F,
						 TNaming_Scope&               MDF,
						 const TopoDS_Shape&               S,
						 const Handle(TNaming_NamedShape)& Context,
						 const Handle(TNaming_NamedShape)& Stop,
						 const Standard_Boolean            Geometry)

{
  // il faut determiner un nouveau context et un nouveau Stop.
  TopoDS_Shape SC;
  Handle(TNaming_NamedShape) NewStop = Stop;
  
  TNaming_Localizer::FindShapeContext (Context,S,SC);
  if (SC.IsNull()) {
    SC = S;
  }

  if(!SC.IsNull()){
// <Context> is Ident.NamedShapeOfGeneration() ==
    TDF_Label Father = Context->Label().Father();
    Father.FindAttribute(TNaming_NamedShape::GetID(),NewStop);
  }
#ifdef DEB
//  cout <<"NewStop shape is  NULL = " << NewStop.IsNull() << endl;  
#endif 
  return BuildName (F,MDF,S,SC,NewStop,Geometry);
}

//=======================================================================
//function : 
//purpose  : 
//=======================================================================

static Handle(TNaming_NamedShape) BuildName (const TDF_Label&                  F,
					     TNaming_Scope&               MDF,
					     const TopoDS_Shape&               Selection,
					     const TopoDS_Shape&               Context,
					     const Handle(TNaming_NamedShape)& Stop,
					     const Standard_Boolean            Geom)

{
  // Create an identifier
  Standard_Boolean OnlyOne      = !Geom;
  Standard_Boolean IsGeneration = Standard_False;;

  TNaming_Identifier Ident(F, Selection, Context,OnlyOne);

  Handle (TNaming_Naming)  Naming;
  Handle (TNaming_NamedShape) NS;

  if (!Ident.IsDone()) {
    return BuildNS (F,Selection, TNaming_UNKNOWN);
  }
  if (Ident.IsFeature() && Stop.IsNull()) {
    //-------------
    // Deja Nomme
    //-------------
    if   (!OnlyOne) return Ident.FeatureArg();
    else            NS =   Ident.FeatureArg();
  }
  else {  
    //---------------------------------------------
    // Construction de la fonction d identification.
    //---------------------------------------------
    //Standard_Boolean NotOnlyOne = 0;

    Naming = TNaming_Naming::Insert(F);
   
    TNaming_Name& theName = Naming->ChangeName();
    theName.ShapeType(Selection.ShapeType());
    theName.Shape(Selection); //szy 21.10.03
    theName.Type(Ident.Type());
#ifdef DEB
//     TCollection_AsciiString E;
//     TDF_Tool::Entry(Naming->Label(), E);
//     cout <<"Inserted Naming Attribute at Label = "<< E << "; NameType = " << theName.Type() <<  endl;
#endif 
    if (Ident.IsFeature()) {
      theName.Append(Ident.FeatureArg());
    }
    if (theName.Type() == TNaming_GENERATION) { 
      theName.Append(Ident.NamedShapeOfGeneration());
      IsGeneration = Standard_True;
    } 
    if (theName.Type() == TNaming_CONSTSHAPE) {
      theName.Index(FindIndex(Ident.FeatureArg(),Selection));
    } 
    //------------------------------------
    // Renseignement du NamedShape d arret.
    //------------------------------------
    theName.StopNamedShape (Stop);
    //---------------------------------
    // Identification des arguments. 
    //---------------------------------

    for (Ident.InitArgs(); Ident.MoreArgs(); Ident.NextArg()) {

      if (Ident.ArgIsFeature())
	theName.Append(Ident.FeatureArg());
      else {
	if (theName.Type() == TNaming_GENERATION) 
	  theName.Append(BuildNameInNS(Naming->Label(),MDF,Ident.ShapeArg(),Ident.NamedShapeOfGeneration(),Stop,Geom));
	
	else 
	  theName.Append(BuildName(Naming->Label(),MDF,Ident.ShapeArg(),Context,Stop,Geom));
      }
    }

    //------------------------
    // Reconstruction of Name
    //------------------------
    Naming->Regenerate(MDF.ChangeValid()); 
    Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
    if(NS.IsNull()) return NS; 
    if (MDF.WithValid()) MDF.Valid(NS->Label());
  }

  if (OnlyOne) {
    //-------------------------------------------------
    // Filtre par les voisins
    // pour construire le nom correspondant a S.
    //------------------------------------------------- 

#ifdef OCC273
   if(NS.IsNull()) return NS; 
#endif

    TNaming_Localizer Localizer;
    TNaming_Iterator itNS(NS); 
    if (itNS.More()) {
      //----------------
      // Check + Filtre
      //----------------

#ifdef OCC350

      Standard_Boolean StandardFilter = !IsGeneration;
      if (IsGeneration) {
	if (!CompareInGeneration (NS,Selection)) {

	  TopoDS_Shape               NewContext;
	  Handle(TNaming_NamedShape) NewStop;
	  FindNewShapeInFather (Ident.NamedShapeOfGeneration(),NewContext);
	  Filter (F,MDF,Selection,NewContext,Localizer,NS);
	}
      } else if (Ident.Type() == TNaming_MODIFUNTIL ||
		 (Ident.Type() == TNaming_INTERSECTION && Naming->ChangeName().Arguments().Extent() == 1)) {
	Handle(TNaming_NamedShape) NewNS =
	  CompareInModification(Ident.Type() == TNaming_MODIFUNTIL ? NS : Naming->ChangeName().Arguments().First(), Selection);
	if (!NewNS.IsNull()) { // there is need to describe name in detail: modification with type 1:n in the same label
	  StandardFilter = Standard_False;
	  if (Ident.IsFeature()) { // for MODIFUNTIL: change it to the GENERATION
	    Naming = TNaming_Naming::Insert(F);
	    TNaming_Name& theName = Naming->ChangeName();
	    theName.ShapeType(Selection.ShapeType());
	    theName.Shape(Selection); //szy 21.10.03
	    theName.Type(TNaming_GENERATION);
	    theName.Append(TNaming_Tool::NamedShape(Selection,F));
	    theName.Append(NewNS);
	    Naming->Regenerate(MDF.ChangeValid());
	    Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
	  }
	  Filter (F,MDF,Selection,Context,Localizer,NS);
	}
      }
      if (StandardFilter) if (!Compare (NS,MDF,Stop,Selection)) {
	Filter (F,MDF,Selection,Context,Localizer,NS);
      }

#else

      if (IsGeneration) {
	if (!CompareInGeneration (NS,Selection)) {
	  TopoDS_Shape               NewContext;
	  Handle(TNaming_NamedShape) NewStop;
	  FindNewShapeInFather (Ident.NamedShapeOfGeneration(),NewContext);
	  Filter (F,MDF,Selection,NewContext,Localizer,NS);
	}
      }
      else {
	if (!Compare (NS,MDF,Stop,Selection))
	  Filter (F,MDF,Selection,Context,Localizer,NS);
      }

#endif

    }
  }
  if (MDF.WithValid()) MDF.Valid(NS->Label());
  return NS;
}

//=======================================================================
//function : Validate
//purpose  : 
//=======================================================================

static void Validate(TNaming_Scope&    MDF,
		     TNaming_OldShapeIterator& it)
{
  MDF.Valid(it.Label()); 
  MDF.ValidChildren(it.Label());

  TNaming_OldShapeIterator it2(it);
  for (; it2.More(); it2.Next()) {
    Validate (MDF,it2);
  }
}

//=======================================================================
//function : UnValidate
//purpose  : 
//=======================================================================

static void UnValidate(TNaming_Scope&    MDF,
		       TNaming_NewShapeIterator& it)
{
  MDF.Unvalid(it.Label()); 
  MDF.UnvalidChildren(it.Label());

  TNaming_NewShapeIterator it2(it);
  for (; it2.More(); it2.Next()) {
    UnValidate (MDF,it2);
  }
}

//=======================================================================
//function : 
//purpose  : 
//=======================================================================

static void BuildScope (TNaming_Scope&    MDF,
			     const TopoDS_Shape&    Context,
			     const TDF_Label&       Acces) 
{
  if (Context.IsNull()) {
    MDF.WithValid(Standard_False);
    return;
  }

  //----------------------------------------------------
  // Is context the current state
  //----------------------------------------------------
  Handle(TNaming_NamedShape) NS   = TNaming_Tool::NamedShape(Context,Acces);
  Handle(TNaming_NamedShape) Next = NextModif(NS);
  if (Next.IsNull()) {  
    MDF.WithValid(Standard_False);
    return;
  }
  //----------------------------- 
  // a posteriori naming
  //-----------------------------  
  MDF.WithValid(Standard_True);
  MDF.Valid(NS->Label());
  MDF.ValidChildren(NS->Label());
  TNaming_OldShapeIterator it(Context,Acces);

  for (; it.More(); it.Next()) {
    Validate(MDF,it);
  }

  TNaming_NewShapeIterator it2(Context,Acces);
  for (;it2.More(); it2.Next()) {
    UnValidate (MDF,it2);
  }
}


//=======================================================================
//function : Name
//purpose  : 
//=======================================================================

Handle(TNaming_NamedShape) TNaming_Naming::Name (const TDF_Label&       F,
						 const TopoDS_Shape&    S,
						 const TopoDS_Shape&    Context,
						 const Standard_Boolean Geom)

{
  //------------------------------------------------------------
  // Construction du MDF tel que <Context> soit le dernier etat
  // valide,
  // Ceci pour les localisation a posteriori par exemple. 
  //------------------------------------------------------------  

  TNaming_Scope MDF;
  BuildScope (MDF,Context,F);

  Handle(TNaming_NamedShape) Stop;

#ifdef OCC352

  if ((S.ShapeType() == TopAbs_SOLID && !TNaming_Tool::NamedShape(S,F).IsNull()) ||

#else

  if (S.ShapeType() == TopAbs_SOLID ||

#endif

      S.ShapeType() == TopAbs_FACE  ||
      S.ShapeType() == TopAbs_EDGE  ||
      S.ShapeType() == TopAbs_VERTEX ) {
    //---------------------------------------
    // Localisation de S comme element simple.
    //---------------------------------------
    Handle(TNaming_NamedShape) NS = BuildName (F,MDF,S,Context,Stop,Geom);
    if (Geom) return NS;
    if (!Geom && TestSolution(MDF,NS,S)) return NS; // <==szy test
  }
  else {
    //----------------------------------------------------
    // Localisation de S comme ensemble d elements simples.
    //-----------------------------------------------------
    Handle(TNaming_NamedShape) NS;
    TopTools_MapOfShape MS;

    Handle (TNaming_Naming)  Naming = TNaming_Naming::Insert(F);
    TNaming_Name&               theName = Naming->ChangeName();

    theName.ShapeType(S.ShapeType());// modified by vro 05.09.00
    theName.Shape(S); //szy 21.10.03
    theName.Type(TNaming_UNION);

#ifdef OCC352

    TopAbs_ShapeEnum atomType;
    switch (S.ShapeType()) {
    case TopAbs_COMPSOLID:
    case TopAbs_SOLID:
    case TopAbs_SHELL:
      atomType = TopAbs_FACE;
      break;
    case TopAbs_WIRE:
      atomType = TopAbs_EDGE;
    default:
      atomType = TopAbs_SHAPE;
    }
    if (atomType == TopAbs_SHAPE) {
      for (TopoDS_Iterator it(S) ; it.More(); it.Next()) {
	theName.Append(BuildName (Naming->Label(),MDF,it.Value(),Context,Stop,Geom));
      }
    } else {
      for (TopExp_Explorer exp(S,atomType) ; exp.More(); exp.Next()) {
	theName.Append(BuildName (Naming->Label(),MDF,exp.Current(),Context,Stop,Geom));
      }
    }

#else
    
    for (TopoDS_Iterator it(S) ; it.More(); it.Next()) {
      theName.Append(BuildName (Naming->Label(),MDF,it.Value(),Context,Stop,Geom));
    }

#endif

    //Naming->Update(); 
    Naming->GetName().Solve(Naming->Label(),MDF.GetValid());

    Naming->Label().FindAttribute(TNaming_NamedShape::GetID(),NS);
    if (Geom) return NS;

#ifdef OCC273
    if(NS.IsNull()) return BuildNS (F,S, TNaming_UNKNOWN);//SZY
#endif

    if (!Geom && TestSolution(MDF,NS,S)) return NS;
  }
  
      cout <<" %%% WARNING: TNaming_Naming::Name:  FAILED"<<endl;

  // Naming n is not satisfactory
  return BuildNS (F,S, TNaming_UNKNOWN);
  
}


//=======================================================================
//function : TNaming_Naming
//purpose  : 
//=======================================================================

TNaming_Naming::TNaming_Naming() {}

//=======================================================================
//function : ID
//purpose  : 
//=======================================================================

const Standard_GUID& TNaming_Naming::ID () const
{
  return GetID(); 
}


//=======================================================================
//function : IsDefined
//purpose  : 
//=======================================================================

Standard_Boolean TNaming_Naming::IsDefined() const
{
  return (myName.Type() != TNaming_UNKNOWN);
}

//=======================================================================
//function : GetName
//purpose  : 
//=======================================================================

const TNaming_Name& TNaming_Naming::GetName() const
{
  return myName;
}

//=======================================================================
//function : ChangeName
//purpose  : 
//=======================================================================

TNaming_Name& TNaming_Naming::ChangeName()
{
  return myName;
}

//=======================================================================
//function : Regenerate
//purpose  : idem designer
//=======================================================================

Standard_Boolean TNaming_Naming::Regenerate (TDF_LabelMap& MDF)  

{
  return myName.Solve(Label(),MDF);
}


//=======================================================================
//function : NewEmpty
//purpose  : 
//=======================================================================

Handle(TDF_Attribute) TNaming_Naming::NewEmpty () const
{  
  return new TNaming_Naming (); 
}


//=======================================================================
//function : Restore
//purpose  : 
//=======================================================================

void TNaming_Naming::Restore(const Handle(TDF_Attribute)& other) 
{
  Handle(TNaming_Naming) OtherNaming = Handle(TNaming_Naming)::DownCast(other);
  myName = OtherNaming->ChangeName();
}

//=======================================================================
//function : Paste
//purpose  : 
//=======================================================================

void TNaming_Naming::Paste (const Handle(TDF_Attribute)& into,
			       const Handle(TDF_RelocationTable)& RT) const
{
  Handle(TNaming_Naming) NewNaming = Handle(TNaming_Naming)::DownCast(into);
  myName.Paste(NewNaming->ChangeName(),RT);
}
  
//=======================================================================
//function : References
//purpose  : Redefined from TDF_Attribute
//=======================================================================

void TNaming_Naming::References(const Handle(TDF_DataSet)& DataSet) const
{
  // Iteration on NamedShape of the name
  TNaming_ListIteratorOfListOfNamedShape it(myName.Arguments());
  for (;it.More();it.Next()) DataSet->AddAttribute(it.Value());
  if (!myName.StopNamedShape().IsNull()) DataSet->AddAttribute(myName.StopNamedShape());
}
//=======================================================================
//function : Dump
//purpose  : 
//=======================================================================

Standard_OStream& TNaming_Naming::Dump (Standard_OStream& anOS) const
{  
  anOS << "TNaming_Naming";
  return anOS;
}


//=======================================================================
//function :ExtendedDump
//purpose  : 
//=======================================================================

void TNaming_Naming::ExtendedDump(Standard_OStream& anOS,
                                  const TDF_IDFilter& /*aFilter*/,
                                  TDF_AttributeIndexedMap& /*aMap*/) const
{
  anOS << "TNaming_Naming ExtendedDump  ";
  //anOS<<"myContext: #" <<aMap.Add(myContext)<<endl; 
}

