// file: $isip/class/mmedia/Annotation/anno_05.cc
// version: $Id: anno_05.cc 8830 2002-11-24 16:43:55Z gao $
//

// isip include files
//
#include "Annotation.h"

// method: getFeature
//
// arguments:
//  const String& feature: (input) annotation feature
//
// return: value of the feature
//
// this method assigns the input object top the current object
//
String Annotation::getFeature(const String& feature_a) {

  // declare local variables
  //
  String value;

  // check if the feature is present
  //
  if (feature_map_d.containsKey(feature_a)) {
    value.assign(*feature_map_d.get(feature_a));
  }

  // return the feature value
  //
  return value;
}

// method: getFeatureNames
//
// arguments:
//  Vector<String>& features: (output) vector of feature names
//
// return: logical error status
//
// method to return a vector of all feature names
//
boolean Annotation::getFeatureNames(Vector<String>& features_a) {

  // declare local variables
  //
  boolean status = false;  

  // get the vector of feature names from the feature map
  //
  status = feature_map_d.keys(features_a);
  
  // return the logical status
  //
  return status;
}

// method: unsetFeatures
//
// arguments: none
//
// return: logical error status
//
// method to set all the features to an empty string
//
boolean Annotation::unsetFeatures() {

  // declare local variables
  //
  String null;
  Vector<String> keys;
  
  // get the vector of values from the feature map
  //
  feature_map_d.keys(keys);

  // loop over all values and set them to null strings
  //
  null.assign(String::EMPTY);
  for (int i = 0; i < keys.length(); i++) {
    feature_map_d.get(keys(i))->assign(null);    
  }
  
  // exit gracefully
  //
  return true;    
}

// method: assign
//
// arguments:
//  const Annotation& arg: (input) annotation object
//
// return: logical error status
//
// this method assigns the input object top the current object
//
boolean Annotation::assign(const Annotation& arg_a) {

  // assign input object to the current object
  //
  id_d.assign(arg_a.id_d);
  type_d.assign(arg_a.type_d);  
  feature_map_d.assign(arg_a.feature_map_d);
  start_d = arg_a.start_d;
  end_d = arg_a.end_d;
  channel_index_d = arg_a.channel_index_d;
  
  // exit gracefully
  //
  return true;
}

// method: sofSize
//
// arguments: none
//
// return: return: size of objec
//
// this method returns the size of the object in the Sof file and is
// used for binary write
//

long Annotation::sofSize() const {

  // declare local variables
  //
  long obj_size = 0;

  // determine the size of the object
  //
  obj_size = type_d.sofSize() + feature_map_d.sofSize();

  // add the space required for the channel index
  //
  obj_size += channel_index_d.sofSize();

  // return the object size
  //
  return obj_size;
}

// method: clear
//
// arguments:
//  Integral::CMODE cmode: (input) clear mode
//
// return: logical error status
//
// this method clears the content of the current object
//
boolean Annotation::clear(Integral::CMODE cmode_a) {

  // clear the member data
  //
  id_d.clear(cmode_a);
  type_d.clear(cmode_a);
  feature_map_d.clear(cmode_a);
  start_d = (Anchor*)NULL;
  end_d = (Anchor*)NULL;
  channel_index_d = DEF_CHANNEL_INDEX;
  
  // exit gracefully
  //
  return true;  
}


// method: compare
//
// arguments:
//  const String& arg1: (input) first anchor id
//  const String& arg2: (input) second anchor id
//
// return: logical error status
//
// this method determines if the base id's are the same
//
boolean Annotation::compare(const String& arg1_a,
			    const String& arg2_a)  const {

  // declare local variables
  //
  long pos1;
  String temp1;
  long pos2;
  String temp2;  

  // find the position of the first delimiter in the id
  //
  pos1 = arg1_a.lastChr(L":");
  pos2 = arg2_a.lastChr(L":");

  // determine the base from the given id for the first
  //
  if (pos1 == Integral::NO_POS) {
    temp1.assign(arg1_a);
  }
  else {
    arg1_a.substr(temp1, pos1, -1);
  }

  // determine the base from the given id for the second
  //  
  if (pos1 == Integral::NO_POS) {
    temp2.assign(arg2_a);
  }
  else {
    arg2_a.substr(temp2, pos2, -1);
  }
  
  // determine if the id's are equal
  //
  return (temp1.eq(temp2));
}

// method: eq
//
// arguments:
//  const Annotation& arg: (input) annotation object
//
// return: logical error status
//
// this method determines if the input object is equal to the current object
//
boolean Annotation::eq(const Annotation& arg_a) const {

  // check if their id's are the same
  //
  if (!compare(id_d, arg_a.id_d)) {
    return false;
  }
  
  // check if their type fields are the same
  //
  if (!type_d.eq(arg_a.type_d)) {
    return false;
  }
  
  // check if the feature maps are the same
  //
  if (!feature_map_d.eq(arg_a.feature_map_d)) {
    return false;
  }
  
  // exit gracefully
  //
  return true;  
}
