/** * Assume that m_xpi.name == search_match. * * @return the parsed OneListSearchMatchImpl or null if the match didn't have a position */ static OneListSearchMatchImpl parse_search_match(MC2Parser mc2p) throws MC2ParserException, IOException { /* * xml 2.3.0 <!ELEMENT search_match ( name, itemid, location_name, lat?, lon?, category_list?, search_area*, detail_field* )> <!ATTLIST search_match search_match_type %search_match_type_t; #REQUIRED category_image CDATA #REQUIRED provider_image CDATA #REQUIRED brand_image CDATA #REQUIRED > <!ENTITY % search_match_type_t "(street|pointofinterest|misc|person| other)"> */ mc2p.nameOrError(MC2Strings.tsearch_match); String matchID = null; String matchLocation = null; String matchName = null; // lat, lon are optional but we skip matches without position // in the future these will be filtered out by the server. Position position = null; // <!ATTLIST search_match search_match_type %search_match_type_t; #REQUIRED // category_image CDATA #REQUIRED // provider_image CDATA #REQUIRED // brand_image CDATA #REQUIRED // additional_info_exists %bool; #REQUIRED > // XML spec for search_match attributes // Images are without file extension and are empty if there is no such // image for the search_match. final String brandImageName = mc2p.attribute(MC2Strings.abrand_image); final String categoryImageName = mc2p.attribute(MC2Strings.acategory_image); final String providerImageName = mc2p.attribute(MC2Strings.aprovider_image); final boolean additionalInfoExists = mc2p.attributeAsBoolean(MC2Strings.aadditional_info_exists); /* <!ELEMENT search_match ( name, itemid, location_name, lat?, lon?, category_list?, //skipped search_area*, //skipped detail_item? )> //included if include_detail_fields is true */ // there is at least 3 subelements mc2p.childrenOrError(); // create this only if we expect info fields PoiDetailImpl detail = null; do { if (mc2p.nameRefEq(MC2Strings.tname)) { // FIXME: MC2Strings matchName = mc2p.value(); } else if (mc2p.nameRefEq(MC2Strings.titemid)) { matchID = mc2p.value(); } else if (mc2p.nameRefEq(MC2Strings.tlat)) { int lat = mc2p.valueAsInt(); if (mc2p.advance() && mc2p.nameRefEq(MC2Strings.tlon)) { int lon = mc2p.valueAsInt(); position = new Position(lat, lon); } } else if (mc2p.nameRefEq(MC2Strings.tlocation_name)) { matchLocation = mc2p.value(); } else if (mc2p.nameRefEq(MC2Strings.tdetail_item)) { detail = mc2p.parseDetailItem(); } } while (mc2p.advance()); mc2p.nameOrError(MC2Strings.tsearch_match); if (position == null) { return null; } else if (matchID == null || matchLocation == null || matchName == null) { throw new MC2ParserException("Invalid data for search_match"); } else { return new OneListSearchMatchImpl( matchID, matchLocation, matchName, position, brandImageName, categoryImageName, providerImageName, detail, additionalInfoExists); } }
/* (non-Javadoc) * @see MC2Request#parse(MC2Parser) */ public void parse(MC2Parser mc2p) throws MC2ParserException, IOException { mc2p.nameOrError(MC2Strings.tone_search_reply); /* * xml 2.3.0 <!ELEMENT one_search_reply ( search_list | ( status_code, status_message, status_uri? ) ) > <!ATTLIST one_search_reply transaction_id ID #REQUIRED > <!ELEMENT search_list ( search_match* )> <!ATTLIST search_list number_matches %number; #REQUIRED total_number_matches %number; #REQUIRED > */ if (LOG.isDebug()) { LOG.debug("OneListSearchMC2Request.parse()", "Parsing compact search reply"); } mc2p.childrenOrError(); // check and report status code ServerError status = mc2p.getErrorIfExists(); if (status != null) { error(status); } else { mc2p.nameOrError(MC2Strings.tsearch_list); int nbr = mc2p.attributeAsInt(MC2Strings.anumber_matches); int estimatedTotal = mc2p.attributeAsInt(MC2Strings.atotal_number_matches); OneListSearchMatchImpl[] matches; if (nbr > 0) { if (nbr <= m_maxNbrMatches) { mc2p.childrenOrError(); matches = new OneListSearchMatchImpl[nbr]; int n = 0; do { if (n < nbr) { OneListSearchMatchImpl match = parse_search_match(mc2p); if (match != null) { matches[n++] = match; } else { if (LOG.isInfo()) { LOG.info("OneListSearchMC2Request.parse()", "match without position, ignored"); } } } else { if (LOG.isWarn()) { LOG.warn( "OneListSearchMC2Request.parse()", "there are more results than requested, skip them"); } } } while (mc2p.advance()); // cope with the matches that didn't have a position // in an ideal world this should never happen if (n < nbr) { // create a clean array if needed OneListSearchMatchImpl[] tmp = matches; matches = new OneListSearchMatchImpl[n]; System.arraycopy(tmp, 0, matches, 0, n); // adjust the total number as we have ignored some result estimatedTotal -= nbr - n; } } else { throw new MC2ParserException( "Nbr " + nbr + " of matches bigegr than max requested " + m_maxNbrMatches); } } else { // if no result create an empty array matches = EMPY_MATCH_ARRAY; } // skip all other elements and go back to parent; // it should be only one call of advance() mc2p.advance(); m_listener.replyReceived(estimatedTotal, matches); } mc2p.nameOrError(MC2Strings.tone_search_reply); }