==========================================
Tagging HSF objects to associate user data
==========================================

If user data needs to be associated with geometry, objects of interest can be 'tagged' by the HOOPS/Stream Toolkit when they are written to the file.

* After an object is tagged, a tagging function can be used to map the object's database ID to its tag and store it as a tag-table entry; this info would then typically be used to store a mapping between user-data and HSF objects.
    
* Then, during reading, a tag-table entry should be created for any tagged items, and then the new database Ids of tagged objects can be accessed to maintain the mapping between user-data and HSF entities.
    
The following provides a detailed example of how to use tags:
  
Let's first assume that we have a 'polyline' primitive in our application data structures with an ID of 1000, and that our application-specific data has a data structure associated with the polyline. When we want to save out our custom data (which could be in either the HSF file or a separate file), let's assume that the data structure will have an ID of 50.
 
 
Writing
-------

#. When we output the polyline, we must call ``BStreamFileToolkit::SetLastKey(ID_Key 1000)`` before the opcode handler's ``Write`` method is called. This tells the toolkit what the 'current' ID is. We then 'tag' the polyline by calling ``BBaseOpcodeHandler::Tag`` (This can be done explicitly by calling 'Tag' within a custom handler, or can be done by asking the toolkit to automatically tag all HSF objects, as we'll discuss later.). Again, this adds an entry to the HSF toolkit's internal tag-table; the entry contains a pair consisting of the ID and a Tag value.

#. Anytime after the polyline has been tagged, we can call the ``BStreamFileToolkit::KeyToIndex`` method, which, given the ID of the polyline, returns to us the file index of the polyline. 

#. Since we know that our custom data associated with the polyline had an ID of 50, we can now store our own mapping between the custom data and the polyline's file Tag returned in Step 2. Specifically, this means that we store the following pair of data somewhere::
  
	[50, (the value returned from KeyToIndex)]

The 'somewhere' could of course be in the HSF file. This would probably be handled by a custom ``TK_User_Data`` object. However, the pairs of mapping data could be external to the HSF file as well; perhaps it is desirable to store it in another user-specific file. The main point is that after reading the HSF objects back in, we will want to retreive the mapping data in order to rebuild a runtime mapping between our custom data and new objects in our graphical database.
  

Reading
-------

1. During the reading process, we first read in the polyline object, and map them it custom application data structures in the overloaded Execute method of our custom polyline opcode handler. (Let's assume that the example polyline discussed above has a new ID of 500 in our app data structures.) We must also call ``BStreamFileToolkit::SetLastKey(ID_Key 500)`` in the ``Execute`` method so that any following tag opcode will result in a properly generated tag-table entry. After the polyline is read in, the toolkit notices that it was tagged, and adds a new entry to the internal tag-table which contains a pair consisting of the new polyline ID (which was set on the toolkit via the call to ``SetLastKey``) and the tag value.

**Note:** The ``Execute`` method should call ``BStreamFileToolkit::SetLastKey(ID_Key)`` for any objects that might be tagged, which include segments and geometry. 

2. We retreive the mapping data that was output in Step 3 of the writing process.

3. We call the ``BStreamFileToolkit::IndexToKey`` method, and pass it the index value that was associated with our custom data value of 50. This returns to us the new ID of the polyline stored in our application data structures, and we can now associate the custom data (id =50) along with the polyline (id = 500) that is stored in our application data structures.

  
Automatic tag generation
------------------------
  
Tags can be automatically generated during the writing process by setting the ``#TK_Force_Tags`` write option::

	int flags = TK_Force_Tags;

	HStreamFileToolkit * tk = new HStreamFileToolkit;
	tk->SetWriteFlags(flags);

All HSF objects which can have tags (such as geometry, segments and includes) will be tagged during writing, and an entry will be added to the HSF toolkit's internal tag-table for each object, which is a pair consisting of the database ID and a tag value. Note that during export of the opcode, we must call ``BStreamFileToolkit::SetLastKey`` before the Write method is called.


Manual tag generation
---------------------

To manually instruct the toolkit to tag specific objects in the HSF file (and add an entry to the HSF toolkit's internal tag-table which is a pair consisting of the database ID and a tag value), the default opcode handler for the object-type of interest must be overloaded so that we can Tag the object within an overloaded Write function. For example, if we only wanted to tag HSF polyline objects, we would instruct the toolkit to use our custom polyline opcode handler::

	tk->SetOpcodeHandler (TKE_Polyline, new My_HTK_Polyline (TKE_Polyline));
	
	// ...
	
	TK_Status My_HTK_Polyline::Write(HStreamFileToolkit &tk)             
	{            
		TK_Status status; 
				 
		// write out the default object 
		if (m_stage!=-1) 
			status = HTK_Polyline::Write(tk);   
				   
		// we are in complete with writing the default object, so we now tag it 
		if (m_stage==-1) 
			status = Tag( tk, -1 );    
				  
		return (status); 
	}          

As discussed previously, we must call ``BStreamFileToolkit::SetLastKey`` before the ``Tag`` function is called.

**Note:** The toolkit automatically tags shell objects (TKE_Shell) during export.
