NetworkedPlanet | TMCore Engine API Guide |
This section contains a little example of how to create a topic
map including two topics and an association. This example also prints
the content of the topic map. This example can be found in the directory
examples/CS/APIExample1
or
examples/VB/APIExample1
.
Example 3.1. Creating a Topic Map
[1] // Initialise the TMCore connection using applicaton configuration settings [2] ITopicMapSystem tmSystem = TopicMapSystemFactory.GetTopicMapSystem(); [4] // Create a new topic map to work in [5] ITopicMap tm = tmSystem.CreateTopicMap("http://www.example.com/topicmaps/MyFirstTopicMap");
In line 2 the static method
TopicMapSystemFactory.GetTopicMapSystem()
is
invoked to create and return a new
ITopicMapSystem
instance. The
no-arguments version of GetTopicMapSystem()
uses the application's configuration file
(APIExample1.exe.config
) to provide the necessary
configuration information. If you are running this application in the
Visual Studio.NET IDE, the file used is the file
App.config
. An example
App.config
is shown below. For a more in-depth look
on whats happening here, please refer to the section called “ITopicMapSystem and TopicMapSystemFactory”. In line 4 a topic map
with the name "http://www.example.com/topicmaps/MyFirstTopicMap" is
created.
Example 3.2. Topic Map Application Configuration File
[1] <configuration> [2] <appSettings> [3] <add key="networkedplanet.tmcore.dbconnect" [4] value="Data Source=localhost;Integrated Security=SSPI; Initial Catalog=topicmap" /> [5] </appSettings> [6] </configuration>
A topic map's name is a unique identifier for the topic map within the TMCore system. Because of this, if you ran an application with the above example code in it twice, you would get a TopicMapExistsException thrown on the second occasion, informing you that a topic map with the specified name already exists. Instead, you should write code that checks that you are not about to create a topic map with a name that is already in use and take the appropriate action if there is. So rather than use the simple code shown in Example 3.1, “Creating a Topic Map”, something like the following code should be invoked:
Example 3.3. Safely Creating a Topic Map
[1] private static ITopicMap SafeCreateTM(ITopicMapSystem tms, string name) [2] { [3] ITopicMap tm = tms.GetTopicMap(name); [4] if (tm != null) [5] { [6] tm.Remove(); [7] } [8] return tms.CreateTopicMap(name); [9] }
On line 3, an attempt is made to retrieve a topic map with the
base locator of the topic map we want to create. If a topic map is
found, we cannot create the new topic map directly. In this example, the
solution is simply to remove the topic map from the system. This is done
using the call to ITopicMap.Remove()
on line 6.
The Remove()
method removes the topic map and
all topics and associations that it contains from the system.
Alternatively you may choose to retry using some algorithm for
generating a new name string that does not already exist or perhaps even
prompt the application user for a new topic map name. Finally on line 8
the topic map is created. In this case, because any pre-existing topic
map with the same name has been removed, the call to the
CreateTopicMap()
method will succeed.
Example 3.4. Creating and Populating Topics
[1] // Create topics [2] ITopic t1 = tm.CreateTopic(); [3] t1.CreateTopicName("hello"); [4] t1.Save(); [6] ITopic t2 = tm.CreateTopic(); [7] t2.CreateTopicName("world"); [8] t2.Save();
Creating a new topic in a topic map is as easy as calling the
CreateTopic()
method on the ITopicMap instance.
The result of this method is a new ITopic
instance. The ITopic interface provides methods for creating new topic
names and occurrences. This is the pattern used throughout the TMCore
API - to create a new object, you call the appropriate
Create...()
method on the parent object. Some
Create...()
methods are overloaded with
different parameter lists to allow you to specify the content of the new
object, so in this example the call to
CreateTopicName()
on lines 3 and 7 take a
single string parameter which is the string value of the newly created
ITopicName
instance.
When an object is modified, the changes are not committed to the
topic map until the Save()
method is called.
The Save()
method is provided on the
ITopic
and the
IAssociation
interfaces only. To save a
change to a topic name or occurrence you must call the
Save()
method on the containing
ITopic
. To save a change to an
IAssociationRole
instance you must call
the Save()
method on the containing
IAssociation
instance. Calling the
Save()
method saves all of the changes made to
the ITopic
or
IAssociation
instance and the saving
takes place in a single database transaction - either all updates are
saved or, in the case of an error, none of the changes are saved.
In addition to Save()
methods on
ITopic
and
IAssociation
, the
ITopicMap
interface also provides a
Save()
method. Invoking this
ITopicMap.Save()
on a topic map will result in
all changes to contained ITopic
and
IAssociation
instances being committed in
a single transaction.
Example 3.5. Creating and Populating Associations
[1] // Create an association between the topics [2] IAssociation a = tm.CreateAssociation(); [3] a.CreateAssociationRole(t1, null); [4] a.CreateAssociationRole(t2, null); [5] a.Save();
Creating an association follows the same pattern as creating a
topic. The IAssociation
instance is
created using the CreateAssociation()
method of
the ITopicMap
interface (line [2]).
IAssociationRole
instances specify the
topics that participate in the association and are created using the
CreateAssociationRole()
method of the
IAssociation
interface. This method takes
two parameters, the first is the ITopic
that is participating in the association and the second is an
ITopic
instance that specifies the type
of role played by the first topic in the association. Either of these
parameters may be null. As with the
ITopic
interface, changes made are not
committed to the database until the
ITopic.Save()
method is called.
Example 3.6. Looping over Topics and Associations
// Print out the names of each topic in the topic map foreach(ITopic t in tm.Topics) { PrintTopicNames(t); } // Print out the role players of each association in the topic map foreach(IAssociation assoc in tm.Associations) { PrintAssociation(assoc); }
The ITopicMap
interface provides
read-only properties Topics and
Associations. These return an
IList
of the topics or associations in
the topic map. Although these properties make it extremely easy to
iterate over the contents of a topic map in a simple application like
this, with large topic maps any simple listing of all topics or all
associations will quickly become difficult to display and potentially
quite slow as you trawl through the whole database! However, for our
simple Hello World application, these properties are extremely
convenient.
Example 3.7. Accessing Topic Data
private static void PrintTopicNames(ITopic t) { System.Console.Write("Topic: "); foreach(ITopicName tn in t.TopicNames) { System.Console.Write("{0} ", tn.Value); } System.Console.WriteLine(); }
Accessing data is as simple as using the properties defined by
each interface. In the example code above, the names of a topic are
returned by the ITopic.TopicNames property which is
a read-only IList
of
ITopicName
instances. The string value of
a topic name is accessed using the ITopicName.Value
property which is a read-write property.
The rule-of-thumb for whether a property will be read-only or
read-write is that if the property gives access to the parent or
children of an object, it will be read-only (you must use the
Create...()
and
Remove()
methods to manage parent-child
relationships). For other properties, access is read-write. So if we
wanted to update a topic name's string value it would be as simple as
:
tn.Value = "My New Name";