// $Id$ #if !defined (ACE_LOCAL_LOCATOR_C) #define ACE_LOCAL_LOCATOR_C #include "Local_Locator.h" #if !defined (__ACE_INLINE__) #include "Local_Locator.i" #endif /* __ACE_INLINE__ */ ACE_RCSID(Caching, Local_Locator, "$Id$") int ACE_URL_Local_Locator::url_query (const ACE_URL_Locator::ACE_Selection_Criteria how, const ACE_URL_Property_Seq *pseq, const size_t how_many, size_t &num_query, ACE_URL_Offer_Seq *offer) { ACE_URL_Record *item = 0; ACE_NEW_RETURN (offer, ACE_URL_Offer_Seq (how_many), -1); if (how >= ACE_URL_Locator::INVALID_SELECTION) { errno = ACE_URL_Locator::INVALID_ARGUMENT; return -1; } num_query = 0; for (ACE_Unbounded_Set_Iterator iter (this->repository_); iter.next (item) != 0; iter.advance ()) { size_t i_query; size_t i_db; int found = 0; // Now this is a stupid implementation. Perhaps we can // implement this using Hash_Map. Better yet, I think we should // put this in a database and put SQL query here. for (i_query = 0; found == 0 && i_query < pseq->size (); i_query++) for (i_db = 0; i_db < item->offer_->url_properties ().size (); i_db++) { if ((*pseq)[i_query].name () == item->offer_->url_properties ()[i_db].name ()) if (how == ACE_URL_Locator::SOME) ; // if match and Some, copy to , inc , advance iterator // else if All, advance iterator // else if None, check next property in . if (all properties checked and found and ALL) copy to ; inc ; else if (all properties checked and not found and NONE) copy to ; inc ; else shouldn't happen, internal error if (num_query == how_many) break; } return 0; } int ACE_URL_Local_Locator::export_offer (ACE_URL_Offer *offer, ACE_WString &offer_id) { ACE_URL_Record *item = 0; // First check if we have registered this URL already. for (ACE_Unbounded_Set_Iterator iter (this->repository_); iter.next (item) != 0; iter.advance ()) if (*item->offer_->url () == *offer->url ()) { errno = ACE_URL_Locator::OFFER_EXIST; return -1; } ACE_URL_Record *new_offer; // Offer is not in repository, we can add new one in safely. ACE_NEW_RETURN (new_offer, ACE_URL_Record (offer), ACE_URL_Locator::NOMEM); this->repository_.push (*new_offer); offer_id = *new_offer->id_; return 0; } int ACE_URL_Local_Locator::withdraw_offer (const ACE_WString &offer_id) { ACE_URL_Record *item = 0; // Iterate thru repository and remove offer with . for (ACE_Unbounded_Set_Iterator iter (this->repository_); iter.next (item) != 0; iter.advance ()) if (offer_id == *item->id_) { if (this->repository_.remove (*item) == 0) return 0 else { errno = ACE_URL_Locator::UNKNOWN; return -1; } } errno = ACE_URL_Locator::NO_SUCH_OFFER; return 0; } int ACE_URL_Local_Locator::describe_offer (const ACE_WString &offer_id, ACE_URL_Offer *offer) { ACE_URL_Record *item = 0; // Iterate thru the repository and produce a copy of offer's // description. for (ACE_Unbounded_Set_Iterator iter (this->repository_); iter.next (item) != 0; iter.advance ()) if (offer_id == *item->id_) { ACE_NEW_RETURN (offer, ACE_URL_Offer (*item->offer_), -1); return 0; } errno = ACE_URL_Locator::NO_SUCH_OFFER; return -1; } int ACE_URL_Local_Locator::modify_offer (const ACE_WString &offer_id, const ACE_WString *url, const ACE_URL_Property_Seq *del, const ACE_URL_Property_Seq *modify) { ACE_Unbounded_Set_Iterator iter (this->repository_); ACE_URL_Record *item = 0; ACE_URL_Record *target = 0; // Errno Checking for (; iter.next (item) != 0; iter.advance ()) { if (url != 0 && *url == item->offer_->url ()) { errno = ACE_URL_Locator::OFFER_EXIST; return -1; } if (offer_id == *item->id_) target = item; } if (target != 0) // Aha, we found a target to work on { if (del != 0 && modify != 0) { // We need to make a copy of the original property sequence // so if any error occurs, we can revert our change easily. // First we need to calculate the maximum number of perperties. int psize = target->offer_->url_properties ().size (); if (del != 0) if ((psize -= del->size ()) < 0) { // If you try to delete more properties than we have, // you are doomed. No need to proceed. errno = ACE_URL_Locator::INVALID_ARGUMENT; return -1; } if (modify != 0) // In the worst case, all properties in will be added. psize += modify->size (); // Now, create a temporary work space. ACE_URL_Property_Seq working (psize); size_t sz = 0; for (; sz < item->offer_->url_properties ().size ()) working[sz] = item->offer_->url_properties() [sz]; if (del != 0) { // Argh, this is really a stupid design. // Go thru every property we want to delete for (size_t i = 0; i < del->size () && sz > 0; i++) // For earch, go thru our property sequence and // search for the property. for (size_t j = 0; j < sz; j++) if ((*del)[i].name () == working[j].name ()) { sz -= 1; working[j] = working[sz]; // pack the array. break; } // Doesn't generate error when we want to delete an // imaginary property. Is this appropriate? } if (modify != 0) { // This is also stupid. // Go thru every property we want to modify/add for (size_t i = 0; i < modify->size () && sz > 0; i++) { // For each property, go thru our property list // and search for the matching property for (size_t j = 0; j < sz; j++) if ((*modify)[i].name () == working[j].name ()) { // A match found. working[j].value ((*modify)[i].value ().fast_rep ()); break; } // No matching property name were found, // We want to add this property into the list. if (j == sz) working[sz++] = (*modify)[i]; } } } // Yes, all operations passed. We can now copy the working version back. item->offer_->url_properties (ACE_URL_Property_Seq (sz)); for (size_t i = 0; i < sz; i ++) item->offer_->url_properties ()[i] = working[i]; if (url != 0) item->offer_->url (url->fast_rep ()); // replace URL location. return 0; } errno = ACE_URL_Locator::NO_SUCH_OFFER; return -1; } #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) template class ACE_Unbounded_Set; template class ACE_Unbounded_Set_Iterator; template class ACE_Node; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) #pragma instantiate ACE_Unbounded_Set #pragma instantiate ACE_Unbounded_Set_Iterator #pragma instantiate ACE_Node #endif /*ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ #endif /* ACE_LOCAL_LOCATOR_C */