5.6 ネットワーク・ユーザー・データ

xxx_SDO_NETWORK_USER_DATAビューを介して定義されたユーザー・データについては、ネットワーク分析中にユーザー・データにアクセスする場合、デフォルトのユーザー・データI/O実装(LODUserDataIOSDO)が使用されます。ただし、一部のユーザー・データは、ノード表またはリンク表に含まれていないため、xxx_SDO_NETWORK_USER_DATAビューを介して登録できません。

このようなユーザー・データについては、ユーザーが、ユーザー・データI/Oインタフェースの独自のカスタム実装を提供する必要があります。カスタムのデータI/Oインタフェースを実装する一般的な方法は、ノードおよびリンクのユーザー・データに対応したBLOB (各パーティションごとに1つのBLOB)を生成してから、ネットワーク分析中にBLOBからユーザー・データ情報を取得することです。

ネットワーク・データ・モデルを使用すると、複数のカテゴリのユーザー定義データ(カテゴリ分けされたユーザー・データ)を単一のネットワークに関連付けることもできます。たとえば、マルチモーダル・ネットワークでは、リンクのマルチモーダル属性の他に、運転に関連する属性(制限速度など)をリンクに関連付ける必要がある場合、ユーザー定義データを2つのカテゴリ(1つは運転に関連する属性用で、もう1つはマルチモーダル属性用)に整理できます。

このようなユーザー定義データの例は、次を参照してください。

5.6.1 ユーザー定義データの例(PL/SQLおよびJava)

この項では、ネットワークのユーザー定義データの使用例を示します。ユーザー定義データとは、ユーザーがネットワーク表現と関連付ける(接続性とは関係のない)情報です。USER_SDO_NETWORK_USER_DATAメタデータ・ビューとALL_SDO_NETWORK_USER_DATAメタデータ・ビュー(「xxx_SDO_NETWORK_USER_DATAビュー」を参照)のどちらにも、ユーザー定義データに関する情報が含まれます。

ユーザー定義データを使用するには、適切なxxx_SDO_NETWORK_METADATAビュー(「xxx_SDO_NETWORK_METADATAビュー」を参照)のUSER_DEFINED_DATA列値をYに設定する必要があります。

例5-1では、リンク関連のユーザー定義データをネットワーク・メタデータに挿入します。

例5-1 ユーザー定義データのネットワーク・メタデータへの挿入

-- Insert link user data named 'interaction' of
-- type varchar2 (50) in network 'bi_test'.
--'interaction' is a column of type varchar2(50) in the link table of network 'bi_
test'.
insert into user_sdo_network_user_data (network, table_type, data_name, data_type, data_length, category_id) 
                  values ('bi_test', 'LINK', 'interaction', 'VARCHAR2', 50, 0) ;
-- insert link user data named 'PROB' of type Number.
--'PROB' is a column of type NUMBER in the link table of network 'bi_test'.
insert into user_sdo_network_user_data (network, table_type, data_name, data_type, category_id)
                  values ('bi_test','LINK','PROB','NUMBER', 0) ;
 
After a network or network partition is loaded, user-defined data is available in Java representations. You can access user-defined data through the getCategorizedUserData and setCategorizedUserData methods for the Node, Link, Path, and SubPath interfaces. For example:
 
//The user data index is the sequence number of a user data within a category sorted by data name.
 
int interactionUserDataIndex = 0;
int probUserDataIndex = 1;
 
String interaction = (String)link.getCategorizedUserData().getUserData(0).
                                get(interactionUseDataIndex);
 
double prob = ((Double)link.getCategorizedUserData().getUserData(0).
                       get(probUserdataIndex)).doubleValue();

5.6.2 ユーザー定義データの例(カスタムのユーザー・データI/O実装)

この項では、LODUserDataIOインタフェースのカスタムのユーザー・データI/O実装(デフォルト以外の実装)の例を示します。例5-2では、リンクに関連付けられたユーザー・データがBLOB (各パーティションごとに1つのBLOB)に書き込まれ、分析中にBLOBから読み込まれます。この例では、各パーティションのマルチモーダル・データに対するユーザー定義データのBLOBには、パーティションIDとパーティションに関連付けられたリンクの数が含まれ、その後に各リンクの<Link ID, link route ID>が含まれていることを前提としています。

例5-2 LODUserDataIOのwriteUserDataメソッドの実装

//Method getLinksInPartition(partitionId) computes a vector that
// consists of  the ID and the route ID of each link associated with a partition
// with ID = partitionId
LinkVector = getLinksInPartition(partitionId);

ObjectOutputStream dout = null;

//Insert an empty blob for the partition with ID = partition_id
String insertStr = "INSERT INTO " + MULTIMODAL_USER_DATA +
                             " (partition_id, blob) " + " VALUES " + " (?, EMPTY_LOB())" ;

PreparedStatement stmt = conn.prepareStatement(insertStr);
stmt.setInt(1,partitionId);
int n = stmt.executeUpdate();
stmt.close();

//lock the row for blob update
 String lockRowStr = "SELECT blob FROM " + MULTIMODAL_USER_DATA +
                                  " WHERE partition_id = ? " + " FOR UPDATE";
 stmt = conn.prepareStatement(lockRowStr);
 stmt.setInt(1,partitionId);
 ResultSet rs = stmt.executeQuery();

 rs.next();
oracle.sql.BLOB userDataBlob = (oracle.sql.BLOB) rs.getBlob(1);
stmt.close();

 OutputStream blobOut = ((oracle.sql.BLOB) userDataBlob).setBinaryStream(1);
 dout = new ObjectOutputStream(blobOut);

 //write partition ID
 dout.writeInt(partitionId);
 int numLinks = linkVector.size()

  for (int i=0; i<linkVector.size(); i++) {
        //MultimodalLink is a class with variables link ID and route ID
        MultimodalLink link = (MultimodalLink) linkVector.elementAt(i);
         //write link ID 
        dout.writeLong(link.getLinkId());

        // write route ID into file
        dout.writeInt(link.getRouteId());
   }
   dout.close();
    blobOut.close();
    rs.close();

後に続く項では、LODUserDataIOインタフェースのwriteUserDataメソッドとreadUserDataメソッドの実装について説明します。

5.6.2.1 LODUserDataIOのwriteUserDataメソッドの実装

LODUserDataIOのwriteUserDataメソッドの実装では、ユーザー定義データのBLOB表の名前がMULTIMODAL_USER_DATAであると想定されています。

//Method getLinksInPartition(partitionId) computes a vector that
// consists of  the ID and the route ID of each link associated with a partition
// with ID = partitionId
LinkVector = getLinksInPartition(partitionId);

ObjectOutputStream dout = null;

//Insert an empty blob for the partition with ID = partition_id
String insertStr = "INSERT INTO " + MULTIMODAL_USER_DATA +
                      " (partition_id, blob) " + " VALUES " + " (?, EMPTY_BLOB())" ;

PreparedStatement stmt = conn.prepareStatement(insertStr);
stmt.setInt(1,partitionId);
int n = stmt.executeUpdate();
stmt.close();

//lock the row for blob update
 String lockRowStr = "SELECT blob FROM " + MULTIMODAL_USER_DATA +
                                  " WHERE partition_id = ? " + " FOR UPDATE";
 stmt = conn.prepareStatement(lockRowStr);
 stmt.setInt(1,partitionId);
 ResultSet rs = stmt.executeQuery();

 rs.next();
oracle.sql.BLOB userDataBlob = (oracle.sql.BLOB) rs.getBlob(1);
stmt.close();

 OutputStream blobOut = ((oracle.sql.BLOB) userDataBlob).setBinaryStream(1);
 dout = new ObjectOutputStream(blobOut);

 //write partition ID
 dout.writeInt(partitionId);
 int numLinks = linkVector.size()

  for (int i=0; i<linkVector.size(); i++) {
        //MultimodalLink is a class with variables link ID and route ID
        MultimodalLink link = (MultimodalLink) linkVector.elementAt(i);
         //write link ID 
        dout.writeLong(link.getLinkId());

        // write route ID into file
        dout.writeInt(link.getRouteId());
   }
   dout.close();
    blobOut.close();
    rs.close();

5.6.2.2 LODUserDataIOのreadUserDataメソッドの実装

ユーザー定義データにアクセスするには、NodeLinkPathおよびSubPathインタフェースのgetCategorizedUserDataメソッドおよびsetCategorizedUserDataメソッド、およびCategorizedUserDataインタフェースのgetUserDataメソッドおよびsetUserDataメソッドを使用します。

//Read the blob for the required partition from the user data blob table
// In this example,
// MULTIMODAL_USER_DATA  is the name of user –defined data blob table
BLOB multimodalBlob = null;
String queryStr = "SELECT blob FROM " + MULTIMODAL_USER_DATA                                
                             " WHERE partition_id = ?";
PreparedStatement stmt = conn.prepareStatement(queryStr);
stmt.setInt(1,partitionId);
ResultSet rs = stmt.executeQuery();
if (rs.next())   {
     multimodalBlob = (oracle.sql.BLOB)rs.getBlob(1);
}
 
// Materialize the blob value as an input stream        
InputStream is = multimodalBlob.getBinaryStream();
 
//Create an ObjectInputStream that reads from the InputStream is
ObjectInputStream ois = new ObjectInputStream(is);
 
//Read the values of partition ID and number of links from the blob
int partitionId = ois.readInt();
int numLinks = ois.readInt();
 
for (int i=0; i<numLinks; i++)  {
 
    //Read link ID and route ID for each link
     long linkId = ois.readLong();
     int routeId = ois.readInt();
 
     //MultimodalLinkUserData is an implementation of NDM LOD UserData interface
     //Implementation is provided at the end of the example 
     linkUserData = new MultimodalLinkUserData(routeId);
 
     //Get the link object corresponding to the link ID
     LogicalNetLink link = partition.getLink(linkId);
 
     //Get the (categorized) user data associated with the link. 
     CategorizedUserData cud = link.getCategorizedUserData();
    
     // If the link does not have categorized user data associated with it,
     // initialize it to linkUserData
     // Else, set the user data for category USER_DATA_MULTIMODAL 
     // to linkUserData 
     if (cud == null) {
            UserData [] userDataArray = {linkUserData};
            cud = new CategorizedUserDataImpl(userDataArray);
             link.setCategorizedUserData(cud);
     }
     else {                   
            cud.setUserData(USER_DATA_MULTIMODAL,linkUserData);
     }
}

次のセグメントでは、分析中にユーザー定義データ(具体的にはリンクに関連付けられたルートID)を読み取る方法を示します。

//info is an instance of LODAnalysisInfo 
LogicalLink currentLink = info.getCurrentLink();
 
//Read the user-defined data (in this case, route ID) 
int linkRouteId   = (Integer)currentLink.getCategorizedUserData().
                           getUserData(USER_DATA_MULTIMODAL).                                      
                           get(INDEX_LINK_ROUTEID);
        
 
Implementation of MultimodalLinkUserData :
 
class MultimodalLinkUserData implements UserData
{
    private int routeId;
 
    protected MultimodalLinkUserData(int routeId)
   {
        this.routeId = routeId;
   }
 
  public Object get(int index)
  {
    switch(index)
    {
         case INDEX_LINK_ROUTEID:
              return routeId;
    }
    return null;
  }
 
  public void set(int index, Object userData)
  {
    switch(index)
    {
         case INDEX_LINK_ROUTEID:
            this.routeId = (Integer) userData;
    }
  }
 
  public int getNumberOfUserData()
  {
       return 1;
  }
 
  public Object clone()
{
    return new MultimodalLinkUserData(routeId);
  }
}