You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-user@axis.apache.org by dustfinger x <du...@muddymukluk.com> on 2011/04/02 22:53:21 UTC

RESTLocation: how best to traverse the tree to map parameters?

// GOAL
Goal: to map uri parameters to their respective values by populating a
map<char*,char*> collection.

// PROBLEM
Problem: The tree structure duplicates nodes and allocates different memory
for those nodes. This makes it somewhat difficult to check if the map
already contains the key before doing an insert. I will illustrate exactly
what my issue is with an example:

Suppose that I have the following RESTLocation defined for the operation
named paramTest.

    <parameter
name="RESTLocation">get/many/param/type/{type}/name/of/{name}/end?param1={aparam1}&param2={aparam2}&param3={aparam3}</parameter>

paramTest will invoke a method called populateUriParameterMap which
populates a map<char*, char*> structure that maps the name of each parameter
to its assigned value. type->atype, name->aname etc... Once the map has been
populated paramTest will iterate over the map and write the associated
values to the axis log.

So when I request the following resource I get the resulting log:
get/many/param/type/atype/name/of/aname/end?param1=foo&param2=bar&param3=foobar

The log shows param1, param2, param3 twice, but with different memory
addresses. I check to see if the map contains these keys before doing the
insert, but it will always pass the test, since it is different memory.

[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param1 [6ca830], second = foo [6d1be0]
[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param2 [6caa80], second = bar [6d1b20]
[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param3 [6cab00], second = foobar [6d1b80]
[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=name [6cabc0], second = aname [6d1a60]
[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param1 [6cad30], second = foo [6d1ac0]
[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=type [6cb160], second = atype [6d1a00]
[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param2 [6cb9d0], second = bar [6d1c40]
[Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param3 [6cbba0], second = foobar [6d1ca0]

Is there a way for me to iterate through the tree and skip these duplicate
nodes? Otherwise I will have to run a value based comparison check on the
maps collection of keys to see if the value of the key is already in the map
and this is not desirable.

// RELEVANT SOURCE CODE BEGIN

/**
 */
axiom_node_t* paramTest(const axutil_env_t *environment, axiom_node_t
*node){

  AXIS2_ENV_CHECK(environment, NULL);

  axiom_node_t *return_node = NULL;

  map<char*, char*> uriParameterMap = map<char*, char*>();
  map<char*, char*>::const_iterator itr;
  populateUriParameterMap(environment, node, uriParameterMap);

  for(itr = uriParameterMap.begin(); itr!=uriParameterMap.end(); itr++){
    char* first = itr->first;
    char* second = itr->second;

    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "queryParam Map first=%s
[%d], second = %s [%d]", first, first, second, second);
  }


  return return_node;
}

void populateUriParameterMap(const axutil_env_t *environment, axiom_node_t
*node, map<char*, char*> &uriParameterMap){

  /* Extracting out the child nodes from the request */
  axiom_node_t *child = axiom_node_get_first_child(node, environment);
  axiom_node_t *sibling = child;

  axis2_char_t* localName = NULL;
  axis2_char_t* textValue = NULL;

  while(sibling && !axiom_node_is_complete(sibling, environment)){
    axiom_types_t nodeType = axiom_node_get_node_type(sibling, environment);
    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "type_node of type [%d]
found ", nodeType);
    axiom_element_t *dataElement =
static_cast<axiom_element_t*>(axiom_node_get_data_element(sibling,
environment));


    localName = axiom_element_get_localname(dataElement, environment);
    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "dataElement->localName
[%s] found ", localName);

    textValue = axiom_element_get_text(dataElement, environment,sibling);

    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "dataElement->text_value
[%s] found ", textValue);

    //insert into map, but first check to see if it already contains the
key.
    //This will always return true since the tree has duplicate nodes with
different memory addresses.
    if(uriParameterMap.end() == uriParameterMap.find(localName)){
      uriParameterMap.insert(pair<char*, char*>(localName, textValue));
    }

    sibling = axiom_node_get_next_sibling(sibling, environment);

  }
}

// RELEVANT SOURCE CODE END

Sincerely,

dustfinger

Re: RESTLocation: how best to traverse the tree to map parameters?

Posted by dustfinger x <du...@muddymukluk.com>.
I resolved the issue by changing the defenition of my map from map<char*,
char*> uriParameterMap = map<char*, char*>(); to
map<string, char*> uriParameterMap = map<char*, char*>(); so now the key is
not a pointer. I am still curious if I am traversing the tree the best way
for what I am trying to accomplish, none the less it seems to be satisfying
my requirements. Here is the output from the logs after changing the
definition of the map

[Sat Apr  2 15:46:54 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=name [6d1ac8], second = aname [6d1a90]
[Sat Apr  2 15:46:54 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param1 [6d1b58], second = foo [6d1b20]
[Sat Apr  2 15:46:54 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param2 [6d1be8], second = bar [6d1bb0]
[Sat Apr  2 15:46:54 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=param3 [6d1c78], second = foobar [6d1c40]
[Sat Apr  2 15:46:54 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
Map first=type [6d1a38], second = atype [6d1a00]

Here is the updated code:

// CODE BEGIN
axiom_node_t* paramTest(const axutil_env_t *environment, axiom_node_t
*node){

  AXIS2_ENV_CHECK(environment, NULL);

  axiom_node_t *return_node = NULL;

  map<string, char*> uriParameterMap = map<string, char*>();
  map<string, char*>::const_iterator itr;
  populateUriParameterMap(environment, node, uriParameterMap);

  //build response
  for(itr = uriParameterMap.begin(); itr!=uriParameterMap.end(); itr++){
    string first = itr->first;
    char* second = itr->second;

    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "queryParam Map first=%s
[%0x], second = %s [%0x]", first.c_str(), first.c_str(), second, second);
  }


  return return_node;
}

void populateUriParameterMap(const axutil_env_t *environment, axiom_node_t
*node, map<string, char*> &uriParameterMap){

  /* Extracting out the child nodes from the request */
  axiom_node_t *child = axiom_node_get_first_child(node, environment);
  axiom_node_t *sibling = child;

  axis2_char_t* localName = NULL;
  axis2_char_t* textValue = NULL;

  while(sibling && !axiom_node_is_complete(sibling, environment)){
    axiom_types_t nodeType = axiom_node_get_node_type(sibling, environment);
    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "type_node of type [%d]
found ", nodeType);
    axiom_element_t *dataElement =
static_cast<axiom_element_t*>(axiom_node_get_data_element(sibling,
environment));


    localName = axiom_element_get_localname(dataElement, environment);
    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "dataElement->localName
[%s] found ", localName);

    textValue = axiom_element_get_text(dataElement, environment,sibling);

    AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "dataElement->text_value
[%s] found ", textValue);

    string sLocalName = localName;
    //insert into map, but first check to see if it already contains the
key.
    if(uriParameterMap.end() == uriParameterMap.find(sLocalName)){
      uriParameterMap.insert(pair<string, char*>(sLocalName, textValue));
    }

    sibling = axiom_node_get_next_sibling(sibling, environment);

  }
}
// CODE END

sincerely,

dustfinger

On Sat, Apr 2, 2011 at 2:53 PM, dustfinger x <du...@muddymukluk.com>wrote:

> // GOAL
> Goal: to map uri parameters to their respective values by populating a
> map<char*,char*> collection.
>
> // PROBLEM
> Problem: The tree structure duplicates nodes and allocates different memory
> for those nodes. This makes it somewhat difficult to check if the map
> already contains the key before doing an insert. I will illustrate exactly
> what my issue is with an example:
>
> Suppose that I have the following RESTLocation defined for the operation
> named paramTest.
>
>     <parameter
> name="RESTLocation">get/many/param/type/{type}/name/of/{name}/end?param1={aparam1}&param2={aparam2}&param3={aparam3}</parameter>
>
> paramTest will invoke a method called populateUriParameterMap which
> populates a map<char*, char*> structure that maps the name of each parameter
> to its assigned value. type->atype, name->aname etc... Once the map has been
> populated paramTest will iterate over the map and write the associated
> values to the axis log.
>
> So when I request the following resource I get the resulting log:
>
> get/many/param/type/atype/name/of/aname/end?param1=foo&param2=bar&param3=foobar
>
> The log shows param1, param2, param3 twice, but with different memory
> addresses. I check to see if the map contains these keys before doing the
> insert, but it will always pass the test, since it is different memory.
>
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=param1 [6ca830], second = foo [6d1be0]
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=param2 [6caa80], second = bar [6d1b20]
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=param3 [6cab00], second = foobar [6d1b80]
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=name [6cabc0], second = aname [6d1a60]
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=param1 [6cad30], second = foo [6d1ac0]
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=type [6cb160], second = atype [6d1a00]
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=param2 [6cb9d0], second = bar [6d1c40]
> [Sat Apr  2 14:45:48 2011] [debug] DataServiceSkeleton.cpp(340) queryParam
> Map first=param3 [6cbba0], second = foobar [6d1ca0]
>
> Is there a way for me to iterate through the tree and skip these duplicate
> nodes? Otherwise I will have to run a value based comparison check on the
> maps collection of keys to see if the value of the key is already in the map
> and this is not desirable.
>
> // RELEVANT SOURCE CODE BEGIN
>
> /**
>  */
> axiom_node_t* paramTest(const axutil_env_t *environment, axiom_node_t
> *node){
>
>   AXIS2_ENV_CHECK(environment, NULL);
>
>   axiom_node_t *return_node = NULL;
>
>   map<char*, char*> uriParameterMap = map<char*, char*>();
>   map<char*, char*>::const_iterator itr;
>   populateUriParameterMap(environment, node, uriParameterMap);
>
>   for(itr = uriParameterMap.begin(); itr!=uriParameterMap.end(); itr++){
>     char* first = itr->first;
>     char* second = itr->second;
>
>     AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "queryParam Map first=%s
> [%d], second = %s [%d]", first, first, second, second);
>   }
>
>
>   return return_node;
> }
>
> void populateUriParameterMap(const axutil_env_t *environment, axiom_node_t
> *node, map<char*, char*> &uriParameterMap){
>
>   /* Extracting out the child nodes from the request */
>   axiom_node_t *child = axiom_node_get_first_child(node, environment);
>   axiom_node_t *sibling = child;
>
>   axis2_char_t* localName = NULL;
>   axis2_char_t* textValue = NULL;
>
>   while(sibling && !axiom_node_is_complete(sibling, environment)){
>     axiom_types_t nodeType = axiom_node_get_node_type(sibling,
> environment);
>     AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "type_node of type [%d]
> found ", nodeType);
>     axiom_element_t *dataElement =
> static_cast<axiom_element_t*>(axiom_node_get_data_element(sibling,
> environment));
>
>
>     localName = axiom_element_get_localname(dataElement, environment);
>     AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "dataElement->localName
> [%s] found ", localName);
>
>     textValue = axiom_element_get_text(dataElement, environment,sibling);
>
>     AXIS2_LOG_USER(environment->log, AXIS2_LOG_SI, "dataElement->text_value
> [%s] found ", textValue);
>
>     //insert into map, but first check to see if it already contains the
> key.
>     //This will always return true since the tree has duplicate nodes with
> different memory addresses.
>     if(uriParameterMap.end() == uriParameterMap.find(localName)){
>       uriParameterMap.insert(pair<char*, char*>(localName, textValue));
>     }
>
>     sibling = axiom_node_get_next_sibling(sibling, environment);
>
>   }
> }
>
> // RELEVANT SOURCE CODE END
>
> Sincerely,
>
> dustfinger
>