Example usage for android.text Html fromHtml

List of usage examples for android.text Html fromHtml

Introduction

In this page you can find the example usage for android.text Html fromHtml.

Prototype

@Deprecated
public static Spanned fromHtml(String source) 

Source Link

Document

Returns displayable styled text from the provided HTML string with the legacy flags #FROM_HTML_MODE_LEGACY .

Usage

From source file:com.vuze.android.remote.SessionInfo.java

public static void showUrlFailedDialog(final Activity activity, final String errMsg, final String url,
        final String sample) {
    if (activity == null) {
        Log.e(null, "No activity for error message " + errMsg);
        return;//from w  w w  .ja  va2  s  .  c o m
    }
    activity.runOnUiThread(new Runnable() {
        public void run() {
            if (activity.isFinishing()) {
                return;
            }
            String s = activity.getResources().getString(R.string.torrent_url_add_failed, url, sample);

            Spanned msg = Html.fromHtml(s);
            Builder builder = new AlertDialog.Builder(activity).setMessage(msg).setCancelable(true)
                    .setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    }).setNeutralButton(R.string.torrent_url_add_failed_openurl, new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                            activity.startActivity(intent);
                        }
                    });
            builder.show();
        }
    });

}

From source file:github.popeen.dsub.fragments.SelectDirectoryFragment.java

private void setupTextDisplay(final View header) {

    final TextView titleView = (TextView) header.findViewById(R.id.select_album_title);
    if (playlistName != null) {
        titleView.setText(playlistName);
    } else if (podcastName != null) {
        Collections.reverse(entries);
        titleView.setText(podcastName);//from  w  w w .j  av a 2s. co  m
        titleView.setPadding(0, 6, 4, 8);
    } else if (name != null) {
        titleView.setText(name);
        if (artistInfo != null) {
            titleView.setPadding(0, 6, 4, 8);
        }
    } else if (share != null) {
        titleView.setVisibility(View.GONE);
    }

    int songCount = 0;

    Set<String> artists = new HashSet<String>();
    Set<Integer> years = new HashSet<Integer>();
    totalDuration = 0;
    for (Entry entry : entries) {
        if (!entry.isDirectory()) {
            songCount++;
            if (entry.getArtist() != null) {
                artists.add(entry.getArtist());
            }
            if (entry.getYear() != null) {
                years.add(entry.getYear());
            }
            Integer duration = entry.getDuration();
            if (duration != null) {
                totalDuration += duration;
            }
        }
    }
    String artistName = "";
    bookDescription = "Could not collect any info about the book at this time";
    try {

        artistName = artists.iterator().next();
        String endpoint = "getBookDirectory";
        if (Util.isTagBrowsing(context)) {
            endpoint = "getBook";
        }
        SharedPreferences prefs = Util.getPreferences(context);
        String url = Util.getRestUrl(context, endpoint) + "&id=" + directory.getId() + "&f=json";

        Log.w("GetInfo", url);
        String artist, title;
        int year = 0;
        artist = title = "";

        try {
            artist = artists.iterator().next();
        } catch (Exception e) {
            Log.w("GetInfoArtist", e.toString());
        }
        try {
            title = titleView.getText().toString();
        } catch (Exception e) {
            Log.w("GetInfoTitle", e.toString());
        }
        try {
            year = years.iterator().next();
        } catch (Exception e) {
            Log.w("GetInfoYear", e.toString());
        }

        BookInfoAPIParams params = new BookInfoAPIParams(url, artist, title, year);
        bookInfo = new BookInfoAPI(context).execute(params).get();
        bookDescription = bookInfo[0];
        bookReader = bookInfo[1];

    } catch (Exception e) {
        Log.w("GetInfoError", e.toString());
    }
    if (bookDescription.equals("noInfo")) {
        bookDescription = "The server has no description for this book";
    }

    final TextView artistView = (TextView) header.findViewById(R.id.select_album_artist);
    if (podcastDescription != null || artistInfo != null || bookDescription != null) {
        artistView.setVisibility(View.VISIBLE);

        String text = "";
        if (bookDescription != null) {
            text = bookDescription;
        }
        if (podcastDescription != null) {
            text = podcastDescription;
        }
        if (artistInfo != null) {
            text = artistInfo.getBiography();
        }
        Spanned spanned = null;
        if (text != null) {
            String newText = "";
            try {
                if (!artistName.equals("")) {
                    newText += "<b>" + context.getResources().getString(R.string.main_artist) + "</b>: "
                            + artistName + "<br/>";
                }
            } catch (Exception e) {
            }
            try {
                if (totalDuration > 0) {
                    newText += "<b>" + context.getResources().getString(R.string.album_book_reader) + "</b>: "
                            + bookReader + "<br/>";
                }
            } catch (Exception e) {
            }
            try {
                if (totalDuration > 0) {
                    newText += "<b>" + context.getResources().getString(R.string.album_book_length) + "</b>: "
                            + Util.formatDuration(totalDuration) + "<br/>";
                }
            } catch (Exception e) {
            }
            try {
                newText += text + "<br/>";
            } catch (Exception e) {
            }
            spanned = Html.fromHtml(newText);
        }

        artistView.setText(spanned);
        artistView.setSingleLine(false);
        final int minLines = context.getResources().getInteger(R.integer.TextDescriptionLength);
        artistView.setLines(minLines);
        artistView.setTextAppearance(context, android.R.style.TextAppearance_Small);

        final Spanned spannedText = spanned;
        artistView.setOnClickListener(new View.OnClickListener() {
            @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
            @Override
            public void onClick(View v) {
                if (artistView.getMaxLines() == minLines) {
                    // Use LeadingMarginSpan2 to try to make text flow around image
                    Display display = context.getWindowManager().getDefaultDisplay();
                    ImageView coverArtView = (ImageView) header.findViewById(R.id.select_album_art);
                    coverArtView.measure(display.getWidth(), display.getHeight());

                    int height, width;
                    ViewGroup.MarginLayoutParams vlp = (ViewGroup.MarginLayoutParams) coverArtView
                            .getLayoutParams();
                    if (coverArtView.getDrawable() != null) {
                        height = coverArtView.getMeasuredHeight() + coverArtView.getPaddingBottom();
                        width = coverArtView.getWidth() + coverArtView.getPaddingRight();
                    } else {
                        height = coverArtView.getHeight();
                        width = coverArtView.getWidth() + coverArtView.getPaddingRight();
                    }
                    float textLineHeight = artistView.getPaint().getTextSize();

                    int lines = (int) Math.ceil(height / textLineHeight) + 1;

                    SpannableString ss = new SpannableString(spannedText);
                    ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(),
                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

                    View linearLayout = header.findViewById(R.id.select_album_text_layout);
                    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) linearLayout
                            .getLayoutParams();
                    int[] rules = params.getRules();
                    rules[RelativeLayout.RIGHT_OF] = 0;
                    params.leftMargin = vlp.rightMargin;

                    artistView.setText(ss);
                    artistView.setMaxLines(100);

                    vlp = (ViewGroup.MarginLayoutParams) titleView.getLayoutParams();
                    vlp.leftMargin = width;
                } else {
                    artistView.setMaxLines(minLines);
                }
            }
        });
        artistView.setMovementMethod(LinkMovementMethod.getInstance());
    } else if (topTracks) {
        artistView.setText(R.string.menu_top_tracks);
        artistView.setVisibility(View.VISIBLE);
    } else if (showAll) {
        artistView.setText(R.string.menu_show_all);
        artistView.setVisibility(View.VISIBLE);
    } else if (artists.size() == 1) {
        String artistText = artists.iterator().next();
        if (years.size() == 1) {
            artistText += " - " + years.iterator().next();
        }
        artistView.setText(artistText);
        artistView.setVisibility(View.VISIBLE);
    } else {
        artistView.setVisibility(View.GONE);
    }

    TextView songCountView = (TextView) header.findViewById(R.id.select_album_song_count);
    TextView songLengthView = (TextView) header.findViewById(R.id.select_album_song_length);
    if (podcastDescription != null || artistInfo != null) {
        songCountView.setVisibility(View.GONE);
        songLengthView.setVisibility(View.GONE);
    } else {
        String s = context.getResources().getQuantityString(R.plurals.select_album_n_songs, songCount,
                songCount);

        songCountView.setVisibility(View.GONE);
        songLengthView.setVisibility(View.GONE);
    }
}

From source file:com.android.messaging.datamodel.MessageNotificationState.java

/**
 * Check for failed messages and post notifications as needed.
 * TODO: Rewrite this as a NotificationState.
 *///from  w w w .ja v  a2 s .  co m
public static void checkFailedMessages() {
    final DatabaseWrapper db = DataModel.get().getDatabase();

    final Cursor messageDataCursor = db.query(DatabaseHelper.MESSAGES_TABLE, MessageData.getProjection(),
            FailedMessageQuery.FAILED_MESSAGES_WHERE_CLAUSE, null /*selectionArgs*/, null /*groupBy*/,
            null /*having*/, FailedMessageQuery.FAILED_ORDER_BY);

    try {
        final Context context = Factory.get().getApplicationContext();
        final Resources resources = context.getResources();
        final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
        if (messageDataCursor != null) {
            final MessageData messageData = new MessageData();

            final HashSet<String> conversationsWithFailedMessages = new HashSet<String>();

            // track row ids in case we want to display something that requires this
            // information
            final ArrayList<Integer> failedMessages = new ArrayList<Integer>();

            int cursorPosition = -1;
            final long when = 0;

            messageDataCursor.moveToPosition(-1);
            while (messageDataCursor.moveToNext()) {
                messageData.bind(messageDataCursor);

                final String conversationId = messageData.getConversationId();
                if (DataModel.get().isNewMessageObservable(conversationId)) {
                    // Don't post a system notification for an observable conversation
                    // because we already show an angry red annotation in the conversation
                    // itself or in the conversation preview snippet.
                    continue;
                }

                cursorPosition = messageDataCursor.getPosition();
                failedMessages.add(cursorPosition);
                conversationsWithFailedMessages.add(conversationId);
            }

            if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
                LogUtil.d(TAG, "Found " + failedMessages.size() + " failed messages");
            }
            if (failedMessages.size() > 0) {
                final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

                CharSequence line1;
                CharSequence line2;
                final boolean isRichContent = false;
                ConversationIdSet conversationIds = null;
                PendingIntent destinationIntent;
                if (failedMessages.size() == 1) {
                    messageDataCursor.moveToPosition(cursorPosition);
                    messageData.bind(messageDataCursor);
                    final String conversationId = messageData.getConversationId();

                    // We have a single conversation, go directly to that conversation.
                    destinationIntent = UIIntents.get().getPendingIntentForConversationActivity(context,
                            conversationId, null /*draft*/);

                    conversationIds = ConversationIdSet.createSet(conversationId);

                    final String failedMessgeSnippet = messageData.getMessageText();
                    int failureStringId;
                    if (messageData.getStatus() == MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED) {
                        failureStringId = R.string.notification_download_failures_line1_singular;
                    } else {
                        failureStringId = R.string.notification_send_failures_line1_singular;
                    }
                    line1 = resources.getString(failureStringId);
                    line2 = failedMessgeSnippet;
                    // Set rich text for non-SMS messages or MMS push notification messages
                    // which we generate locally with rich text
                    // TODO- fix this
                    //                        if (messageData.isMmsInd()) {
                    //                            isRichContent = true;
                    //                        }
                } else {
                    // We have notifications for multiple conversation, go to the conversation
                    // list.
                    destinationIntent = UIIntents.get().getPendingIntentForConversationListActivity(context);

                    int line1StringId;
                    int line2PluralsId;
                    if (messageData.getStatus() == MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED) {
                        line1StringId = R.string.notification_download_failures_line1_plural;
                        line2PluralsId = R.plurals.notification_download_failures;
                    } else {
                        line1StringId = R.string.notification_send_failures_line1_plural;
                        line2PluralsId = R.plurals.notification_send_failures;
                    }
                    line1 = resources.getString(line1StringId);
                    line2 = resources.getQuantityString(line2PluralsId, conversationsWithFailedMessages.size(),
                            failedMessages.size(), conversationsWithFailedMessages.size());
                }
                line1 = applyWarningTextColor(context, line1);
                line2 = applyWarningTextColor(context, line2);

                final PendingIntent pendingIntentForDelete = UIIntents.get()
                        .getPendingIntentForClearingNotifications(context, BugleNotifications.UPDATE_ERRORS,
                                conversationIds, 0);

                builder.setContentTitle(line1).setTicker(line1)
                        .setWhen(when > 0 ? when : System.currentTimeMillis())
                        .setSmallIcon(R.drawable.ic_failed_light).setDeleteIntent(pendingIntentForDelete)
                        .setContentIntent(destinationIntent)
                        .setSound(UriUtil.getUriForResourceId(context, R.raw.message_failure));
                if (isRichContent && !TextUtils.isEmpty(line2)) {
                    final NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(builder);
                    if (line2 != null) {
                        inboxStyle.addLine(Html.fromHtml(line2.toString()));
                    }
                    builder.setStyle(inboxStyle);
                } else {
                    builder.setContentText(line2);
                }

                if (builder != null) {
                    notificationManager.notify(BugleNotifications
                            .buildNotificationTag(PendingIntentConstants.MSG_SEND_ERROR, null),
                            PendingIntentConstants.MSG_SEND_ERROR, builder.build());
                }
            } else {
                notificationManager.cancel(
                        BugleNotifications.buildNotificationTag(PendingIntentConstants.MSG_SEND_ERROR, null),
                        PendingIntentConstants.MSG_SEND_ERROR);
            }
        }
    } finally {
        if (messageDataCursor != null) {
            messageDataCursor.close();
        }
    }
}

From source file:com.ichi2.anki.NoteEditor.java

/** Update the list of card templates for current note type */
private void updateCards(JSONObject model) {
    try {//from w  ww.j a  v a  2 s .com
        JSONArray tmpls = model.getJSONArray("tmpls");
        String cardsList = "";
        // Build comma separated list of card names
        for (int i = 0; i < tmpls.length(); i++) {
            String name = tmpls.getJSONObject(i).optString("name");
            // If more than one card then make currently selected card underlined
            if (!mAddNote && tmpls.length() > 1 && model == mEditorNote.model()
                    && mCurrentEditedCard.template().optString("name").equals(name)) {
                name = "<u>" + name + "</u>";
            }
            cardsList += name;
            if (i < tmpls.length() - 1) {
                cardsList += ", ";
            }
        }
        // Make cards list red if the number of cards is being reduced
        if (!mAddNote && tmpls.length() < mEditorNote.model().getJSONArray("tmpls").length()) {
            cardsList = "<font color='red'>" + cardsList + "</font>";
        }
        mCardsButton.setText(Html.fromHtml(getResources().getString(R.string.CardEditorCards, cardsList)));
    } catch (JSONException e) {
        throw new RuntimeException(e);
    }
}

From source file:cl.ipp.katbag.fragment.Develop.java

public void setLook(String title, final String humanTextRow, final int dialogIdObjectItemList,
        final long object_id) {
    int resource = getResources().getIdentifier("dialog_look_" + dialogIdObjectItemList, "layout",
            mainActivity.getPackageName());
    LayoutInflater inflater = LayoutInflater.from(mainActivity.context);
    final View dialog_layout = inflater.inflate(resource, null);

    if (object_id != -1) {
        dev.clear();//w  ww.j a v  a 2s . c o m
        dev = mainActivity.katbagHandler.selectDevelopForId(object_id);
    }

    spinner_drawing_1 = (Spinner) dialog_layout.findViewById(R.id.dialog_drawing_1);
    spinner_drawing_2 = (Spinner) dialog_layout.findViewById(R.id.dialog_drawing_2);

    spinnerList.clear();
    drawing1List.clear();
    spinnerList = mainActivity.katbagHandler.selectDevelopAllDrawing(id_app);
    if (spinnerList.size() == 0) {
        KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_not_drawing));
        return;
    }

    for (int i = 0; i < spinnerList.size(); i++) {
        drawing1List.add(getString(R.string.drawings_row_name) + " " + spinnerList.get(i));
    }

    ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(mainActivity.context,
            R.layout.simple_spinner_item_custom, drawing1List);
    arrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item_custom);
    spinner_drawing_1.setAdapter(arrayAdapter);

    switch (dialogIdObjectItemList) {
    case 0:
        if (object_id == -1) {

        } else {
            for (int i = 0; i < spinnerList.size(); i++) {
                if (spinnerList.get(i).contentEquals(dev.get(3))) {
                    spinner_drawing_1.setSelection(i);
                    break;
                }
            }
        }
        break;

    case 1:
        if (object_id == -1) {

        } else {
            for (int i = 0; i < spinnerList.size(); i++) {
                if (spinnerList.get(i).contentEquals(dev.get(3))) {
                    spinner_drawing_1.setSelection(i);
                    break;
                }
            }
        }
        break;

    case 2:
        spinner_drawing_2.setAdapter(arrayAdapter);

        if (object_id == -1) {
            if (spinnerList.size() > 1) {
                spinner_drawing_2.setSelection(1);
            }

        } else {
            for (int i = 0; i < spinnerList.size(); i++) {
                if (spinnerList.get(i).contentEquals(dev.get(3))) {
                    spinner_drawing_1.setSelection(i);
                    break;
                }
            }

            for (int i = 0; i < spinnerList.size(); i++) {
                if (spinnerList.get(i).contentEquals(dev.get(4))) {
                    spinner_drawing_2.setSelection(i);
                    break;
                }
            }
        }
        break;
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity.context);
    builder.setView(dialog_layout);
    builder.setTitle(Html.fromHtml(title));
    builder.setNegativeButton(getString(R.string.dialog_button_cancel), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            // :)
        }
    });

    builder.setPositiveButton(getString(R.string.dialog_button_ok), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            drawingText_1 = spinner_drawing_1.getSelectedItem().toString();
            drawingId_1 = spinnerList.get(spinner_drawing_1.getSelectedItemPosition());

            switch (dialogIdObjectItemList) {
            case 0:
                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "look",
                            String.format(humanTextRow, drawingText_1), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type look
                            drawingId_1, // id of drawing selected
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "look",
                            String.format(humanTextRow, drawingText_1), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type look
                            drawingId_1, // id of drawing selected
                            "", "", "", "", "", "");
                }
                break;

            case 1:
                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "look",
                            String.format(humanTextRow, drawingText_1), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type look
                            drawingId_1, // id of drawing selected
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "look",
                            String.format(humanTextRow, drawingText_1), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type look
                            drawingId_1, // id of drawing selected
                            "", "", "", "", "", "");
                }
                break;

            case 2:
                // validate field
                if (spinner_drawing_1.getSelectedItemPosition() == spinner_drawing_2
                        .getSelectedItemPosition()) {
                    KatbagUtilities.message(mainActivity.context,
                            getString(R.string.develop_message_not_different));
                    return;
                }

                drawingText_2 = spinner_drawing_2.getSelectedItem().toString();
                drawingId_2 = spinnerList.get(spinner_drawing_2.getSelectedItemPosition());

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "look",
                            String.format(humanTextRow, drawingText_1, drawingText_2), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type look
                            drawingId_1, // id of first drawing selected
                            drawingId_2, // id of second drawing selected
                            "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "look",
                            String.format(humanTextRow, drawingText_1, drawingText_2), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type look
                            drawingId_1, // id of first drawing selected
                            drawingId_2, // id of second drawing selected
                            "", "", "", "", "");
                }
                break;
            }

            loadListView();
        }
    });

    builder.show();
}

From source file:cgeo.geocaching.cgBase.java

public cgCacheWrap parseCache(String page, int reason) {
    if (StringUtils.isBlank(page)) {
        Log.e(cgSettings.tag, "cgeoBase.parseCache: No page given");
        return null;
    }//from   w ww  . j  av  a  2 s .  c  o  m

    final cgCacheWrap caches = new cgCacheWrap();
    final cgCache cache = new cgCache();

    if (page.contains("Cache is Unpublished")) {
        caches.error = "cache was unpublished";
        return caches;
    }

    if (page.contains("Sorry, the owner of this listing has made it viewable to Premium Members only.")) {
        caches.error = "requested cache is for premium members only";
        return caches;
    }

    if (page.contains("has chosen to make this cache listing visible to Premium Members only.")) {
        caches.error = "requested cache is for premium members only";
        return caches;
    }

    cache.disabled = page.contains("<li>This cache is temporarily unavailable.");

    cache.archived = page.contains("<li>This cache has been archived,");

    cache.members = page.contains("<p class=\"Warning\">This is a Premium Member Only cache.</p>");

    cache.reason = reason;

    // cache geocode
    try {
        final Matcher matcherGeocode = patternGeocode.matcher(page);
        if (matcherGeocode.find() && matcherGeocode.groupCount() > 0) {
            cache.geocode = getMatch(matcherGeocode.group(1));
        }
    } catch (Exception e) {
        // failed to parse cache geocode
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache geocode");
    }

    // cache id
    try {
        final Matcher matcherCacheId = patternCacheId.matcher(page);
        if (matcherCacheId.find() && matcherCacheId.groupCount() > 0) {
            cache.cacheId = getMatch(matcherCacheId.group(1));
        }
    } catch (Exception e) {
        // failed to parse cache id
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache id");
    }

    // cache guid
    try {
        final Matcher matcherCacheGuid = patternCacheGuid.matcher(page);
        if (matcherCacheGuid.find() && matcherCacheGuid.groupCount() > 0) {
            cache.guid = getMatch(matcherCacheGuid.group(1));
        }
    } catch (Exception e) {
        // failed to parse cache guid
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache guid");
    }

    // name
    try {
        final Matcher matcherName = patternName.matcher(page);
        if (matcherName.find() && matcherName.groupCount() > 0) {
            cache.name = Html.fromHtml(matcherName.group(1)).toString();
        }
    } catch (Exception e) {
        // failed to parse cache name
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache name");
    }

    // owner real name
    try {
        final Matcher matcherOwnerReal = patternOwnerReal.matcher(page);
        if (matcherOwnerReal.find() && matcherOwnerReal.groupCount() > 0) {
            cache.ownerReal = URLDecoder.decode(matcherOwnerReal.group(1));
        }
    } catch (Exception e) {
        // failed to parse owner real name
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache owner real name");
    }

    final String username = settings.getUsername();
    if (cache.ownerReal != null && username != null && cache.ownerReal.equalsIgnoreCase(username)) {
        cache.own = true;
    }

    int pos = -1;
    String tableInside = page;

    pos = tableInside.indexOf("id=\"cacheDetails\"");
    if (pos == -1) {
        Log.e(cgSettings.tag, "cgeoBase.parseCache: ID \"cacheDetails\" not found on page");
        return null;
    }

    tableInside = tableInside.substring(pos);

    pos = tableInside.indexOf("<div class=\"CacheInformationTable\"");
    if (pos == -1) {
        Log.e(cgSettings.tag, "cgeoBase.parseCache: ID \"CacheInformationTable\" not found on page");
        return null;
    }

    tableInside = tableInside.substring(0, pos);

    if (StringUtils.isNotBlank(tableInside)) {
        // cache terrain
        try {
            final Matcher matcherTerrain = patternTerrain.matcher(tableInside);
            if (matcherTerrain.find() && matcherTerrain.groupCount() > 0) {
                cache.terrain = new Float(
                        Pattern.compile("_").matcher(matcherTerrain.group(1)).replaceAll("."));
            }
        } catch (Exception e) {
            // failed to parse terrain
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache terrain");
        }

        // cache difficulty
        try {
            final Matcher matcherDifficulty = patternDifficulty.matcher(tableInside);
            if (matcherDifficulty.find() && matcherDifficulty.groupCount() > 0) {
                cache.difficulty = new Float(
                        Pattern.compile("_").matcher(matcherDifficulty.group(1)).replaceAll("."));
            }
        } catch (Exception e) {
            // failed to parse difficulty
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache difficulty");
        }

        // owner
        try {
            final Matcher matcherOwner = patternOwner.matcher(tableInside);
            if (matcherOwner.find() && matcherOwner.groupCount() > 0) {
                cache.owner = Html.fromHtml(matcherOwner.group(2)).toString();
            }
        } catch (Exception e) {
            // failed to parse owner
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache owner");
        }

        // hidden
        try {
            final Matcher matcherHidden = patternHidden.matcher(tableInside);
            if (matcherHidden.find() && matcherHidden.groupCount() > 0) {
                cache.hidden = parseGcCustomDate(matcherHidden.group(1));
            }
        } catch (ParseException e) {
            // failed to parse cache hidden date
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache hidden date");
        }

        if (cache.hidden == null) {
            // event date
            try {
                final Matcher matcherHiddenEvent = patternHiddenEvent.matcher(tableInside);
                if (matcherHiddenEvent.find() && matcherHiddenEvent.groupCount() > 0) {
                    cache.hidden = parseGcCustomDate(matcherHiddenEvent.group(1));
                }
            } catch (ParseException e) {
                // failed to parse cache event date
                Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache event date");
            }
        }

        // favourite
        try {
            final Matcher matcherFavourite = patternFavourite.matcher(tableInside);
            if (matcherFavourite.find() && matcherFavourite.groupCount() > 0) {
                cache.favouriteCnt = Integer.parseInt(matcherFavourite.group(1));
            }
        } catch (Exception e) {
            // failed to parse favourite count
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse favourite count");
        }

        // cache size
        try {
            final Matcher matcherSize = patternSize.matcher(tableInside);
            if (matcherSize.find() && matcherSize.groupCount() > 0) {
                cache.size = CacheSize.FIND_BY_ID.get(getMatch(matcherSize.group(1)).toLowerCase());
            }
        } catch (Exception e) {
            // failed to parse size
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache size");
        }
    }

    // cache found
    cache.found = patternFound.matcher(page).find() || patternFoundAlternative.matcher(page).find();

    // cache type
    try {
        final Matcher matcherType = patternType.matcher(page);
        if (matcherType.find() && matcherType.groupCount() > 0) {
            cache.type = cacheTypes.get(matcherType.group(1).toLowerCase());
        }
    } catch (Exception e) {
        // failed to parse type
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache type");
    }

    // on watchlist
    try {
        final Matcher matcher = patternOnWatchlist.matcher(page);
        cache.onWatchlist = matcher.find();
    } catch (Exception e) {
        // failed to parse watchlist state
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse watchlist state");
    }

    // latitude and logitude
    try {
        final Matcher matcherLatLon = patternLatLon.matcher(page);
        if (matcherLatLon.find() && matcherLatLon.groupCount() > 0) {
            cache.latlon = getMatch(matcherLatLon.group(2)); // first is <b>

            Map<String, Object> tmp = cgBase.parseLatlon(cache.latlon);
            if (tmp.size() > 0) {
                cache.coords = new Geopoint((Double) tmp.get("latitude"), (Double) tmp.get("longitude"));
                cache.latitudeString = (String) tmp.get("latitudeString");
                cache.longitudeString = (String) tmp.get("longitudeString");
                cache.reliableLatLon = true;
            }
            tmp = null;
        }
    } catch (Exception e) {
        // failed to parse latitude and/or longitude
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache coordinates");
    }

    // cache location
    try {
        final Matcher matcherLocation = patternLocation.matcher(page);
        if (matcherLocation.find() && matcherLocation.groupCount() > 0) {
            cache.location = getMatch(matcherLocation.group(1));
        }
    } catch (Exception e) {
        // failed to parse location
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache location");
    }

    // cache hint
    try {
        final Matcher matcherHint = patternHint.matcher(page);
        if (matcherHint.find() && matcherHint.group(1) != null) {
            // replace linebreak and paragraph tags
            String hint = Pattern.compile("<(br|p)[^>]*>").matcher(matcherHint.group(1)).replaceAll("\n");
            if (hint != null) {
                cache.hint = hint.replaceAll(Pattern.quote("</p>"), "").trim();
            }
        }
    } catch (Exception e) {
        // failed to parse hint
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache hint");
    }

    checkFields(cache);
    /*
     * // short info debug
     * Log.d(cgSettings.tag, "gc-code: " + cache.geocode);
     * Log.d(cgSettings.tag, "id: " + cache.cacheid);
     * Log.d(cgSettings.tag, "guid: " + cache.guid);
     * Log.d(cgSettings.tag, "name: " + cache.name);
     * Log.d(cgSettings.tag, "terrain: " + cache.terrain);
     * Log.d(cgSettings.tag, "difficulty: " + cache.difficulty);
     * Log.d(cgSettings.tag, "owner: " + cache.owner);
     * Log.d(cgSettings.tag, "owner (real): " + cache.ownerReal);
     * Log.d(cgSettings.tag, "hidden: " + dateOutShort.format(cache.hidden));
     * Log.d(cgSettings.tag, "favorite: " + cache.favouriteCnt);
     * Log.d(cgSettings.tag, "size: " + cache.size);
     * if (cache.found) {
     * Log.d(cgSettings.tag, "found!");
     * } else {
     * Log.d(cgSettings.tag, "not found");
     * }
     * Log.d(cgSettings.tag, "type: " + cache.type);
     * Log.d(cgSettings.tag, "latitude: " + String.format("%.6f", cache.latitude));
     * Log.d(cgSettings.tag, "longitude: " + String.format("%.6f", cache.longitude));
     * Log.d(cgSettings.tag, "location: " + cache.location);
     * Log.d(cgSettings.tag, "hint: " + cache.hint);
     */

    // cache personal note
    try {
        final Matcher matcherPersonalNote = patternPersonalNote.matcher(page);
        if (matcherPersonalNote.find() && matcherPersonalNote.groupCount() > 0) {
            cache.personalNote = getMatch(matcherPersonalNote.group(1));
        }
    } catch (Exception e) {
        // failed to parse cache personal note
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache personal note");
    }

    // cache short description
    try {
        final Matcher matcherDescShort = patternDescShort.matcher(page);
        if (matcherDescShort.find() && matcherDescShort.groupCount() > 0) {
            cache.shortdesc = getMatch(matcherDescShort.group(1));
        }
    } catch (Exception e) {
        // failed to parse short description
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache short description");
    }

    // cache description
    try {
        final Matcher matcherDesc = patternDesc.matcher(page);
        if (matcherDesc.find() && matcherDesc.groupCount() > 0) {
            cache.description = getMatch(matcherDesc.group(1));
        }
    } catch (Exception e) {
        // failed to parse short description
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache description");
    }

    // cache attributes
    try {
        final Matcher matcherAttributes = patternAttributes.matcher(page);
        if (matcherAttributes.find() && matcherAttributes.groupCount() > 0) {
            final String attributesPre = matcherAttributes.group(1);
            final Matcher matcherAttributesInside = patternAttributesInside.matcher(attributesPre);

            while (matcherAttributesInside.find()) {
                if (matcherAttributesInside.groupCount() > 1
                        && matcherAttributesInside.group(2).equalsIgnoreCase("blank") != true) {
                    if (cache.attributes == null) {
                        cache.attributes = new ArrayList<String>();
                    }
                    // by default, use the tooltip of the attribute
                    String attribute = matcherAttributesInside.group(2).toLowerCase();

                    // if the image name can be recognized, use the image name as attribute
                    String imageName = matcherAttributesInside.group(1).trim();
                    if (imageName.length() > 0) {
                        int start = imageName.lastIndexOf('/');
                        int end = imageName.lastIndexOf('.');
                        if (start >= 0 && end >= 0) {
                            attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase();
                        }
                    }
                    cache.attributes.add(attribute);
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache attributes
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache attributes");
    }

    // cache spoilers
    try {
        final Matcher matcherSpoilers = patternSpoilers.matcher(page);
        if (matcherSpoilers.find()) {
            final Matcher matcherSpoilersInside = patternSpoilersInside.matcher(matcherSpoilers.group(1));

            while (matcherSpoilersInside.find()) {
                final cgImage spoiler = new cgImage();
                spoiler.url = matcherSpoilersInside.group(1);

                if (matcherSpoilersInside.group(2) != null) {
                    spoiler.title = matcherSpoilersInside.group(2);
                }
                if (matcherSpoilersInside.group(3) != null) {
                    spoiler.description = matcherSpoilersInside.group(3);
                }

                if (cache.spoilers == null) {
                    cache.spoilers = new ArrayList<cgImage>();
                }
                cache.spoilers.add(spoiler);
            }
        }
    } catch (Exception e) {
        // failed to parse cache spoilers
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache spoilers");
    }

    // cache inventory
    try {
        cache.inventoryItems = 0;

        final Matcher matcherInventory = patternInventory.matcher(page);
        if (matcherInventory.find()) {
            if (cache.inventory == null) {
                cache.inventory = new ArrayList<cgTrackable>();
            }

            if (matcherInventory.groupCount() > 1) {
                final String inventoryPre = matcherInventory.group(2);

                if (StringUtils.isNotBlank(inventoryPre)) {
                    final Matcher matcherInventoryInside = patternInventoryInside.matcher(inventoryPre);

                    while (matcherInventoryInside.find()) {
                        if (matcherInventoryInside.groupCount() > 0) {
                            final cgTrackable inventoryItem = new cgTrackable();
                            inventoryItem.guid = matcherInventoryInside.group(1);
                            inventoryItem.name = matcherInventoryInside.group(2);

                            cache.inventory.add(inventoryItem);
                            cache.inventoryItems++;
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache inventory
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache inventory (2)");
    }

    // cache logs counts
    try {
        final Matcher matcherLogCounts = patternCountLogs.matcher(page);

        if (matcherLogCounts.find()) {
            final Matcher matcherLog = patternCountLog.matcher(matcherLogCounts.group(1));

            while (matcherLog.find()) {
                String typeStr = matcherLog.group(1);
                String countStr = matcherLog.group(2).replaceAll("[.,]", "");

                if (StringUtils.isNotBlank(typeStr) && logTypes.containsKey(typeStr.toLowerCase())
                        && StringUtils.isNotBlank(countStr)) {
                    cache.logCounts.put(logTypes.get(typeStr.toLowerCase()), Integer.parseInt(countStr));
                }
            }
        }
    } catch (Exception e) {
        // failed to parse logs
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache log count");
    }

    // cache logs
    loadLogsFromDetails(page, cache);

    int wpBegin = 0;
    int wpEnd = 0;

    wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
    if (wpBegin != -1) { // parse waypoints
        final Pattern patternWpType = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg",
                Pattern.CASE_INSENSITIVE);
        final Pattern patternWpPrefixOrLookupOrLatlon = Pattern
                .compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>", Pattern.CASE_INSENSITIVE);
        final Pattern patternWpName = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>", Pattern.CASE_INSENSITIVE);
        final Pattern patternWpNote = Pattern.compile("colspan=\"6\">(.*)<\\/td>", Pattern.CASE_INSENSITIVE);

        String wpList = page.substring(wpBegin);

        wpEnd = wpList.indexOf("</p>");
        if (wpEnd > -1 && wpEnd <= wpList.length()) {
            wpList = wpList.substring(0, wpEnd);
        }

        if (!wpList.contains("No additional waypoints to display.")) {
            wpEnd = wpList.indexOf("</table>");
            wpList = wpList.substring(0, wpEnd);

            wpBegin = wpList.indexOf("<tbody>");
            wpEnd = wpList.indexOf("</tbody>");
            if (wpBegin >= 0 && wpEnd >= 0 && wpEnd <= wpList.length()) {
                wpList = wpList.substring(wpBegin + 7, wpEnd);
            }

            final String[] wpItems = wpList.split("<tr");

            String[] wp;
            for (int j = 1; j < wpItems.length; j++) {
                final cgWaypoint waypoint = new cgWaypoint();

                wp = wpItems[j].split("<td");

                // waypoint type
                try {
                    final Matcher matcherWpType = patternWpType.matcher(wp[3]);
                    if (matcherWpType.find() && matcherWpType.groupCount() > 0) {
                        waypoint.type = matcherWpType.group(1).trim();
                    }
                } catch (Exception e) {
                    // failed to parse type
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint type");
                }

                // waypoint prefix
                try {
                    final Matcher matcherWpPrefix = patternWpPrefixOrLookupOrLatlon.matcher(wp[4]);
                    if (matcherWpPrefix.find() && matcherWpPrefix.groupCount() > 1) {
                        waypoint.setPrefix(matcherWpPrefix.group(2).trim());
                    }
                } catch (Exception e) {
                    // failed to parse prefix
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint prefix");
                }

                // waypoint lookup
                try {
                    final Matcher matcherWpLookup = patternWpPrefixOrLookupOrLatlon.matcher(wp[5]);
                    if (matcherWpLookup.find() && matcherWpLookup.groupCount() > 1) {
                        waypoint.lookup = matcherWpLookup.group(2).trim();
                    }
                } catch (Exception e) {
                    // failed to parse lookup
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint lookup");
                }

                // waypoint name
                try {
                    final Matcher matcherWpName = patternWpName.matcher(wp[6]);
                    while (matcherWpName.find()) {
                        if (matcherWpName.groupCount() > 0) {
                            waypoint.name = matcherWpName.group(1);
                            if (StringUtils.isNotBlank(waypoint.name)) {
                                waypoint.name = waypoint.name.trim();
                            }
                        }
                        if (matcherWpName.find() && matcherWpName.groupCount() > 0) {
                            waypoint.name = matcherWpName.group(1).trim();
                        }
                    }
                } catch (Exception e) {
                    // failed to parse name
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint name");
                }

                // waypoint latitude and logitude
                try {
                    final Matcher matcherWpLatLon = patternWpPrefixOrLookupOrLatlon.matcher(wp[7]);
                    if (matcherWpLatLon.find() && matcherWpLatLon.groupCount() > 1) {
                        waypoint.latlon = Html.fromHtml(matcherWpLatLon.group(2)).toString();

                        final Map<String, Object> tmp = cgBase.parseLatlon(waypoint.latlon);
                        if (tmp.size() > 0) {
                            waypoint.coords = new Geopoint((Double) tmp.get("latitude"),
                                    (Double) tmp.get("longitude"));
                            waypoint.latitudeString = (String) tmp.get("latitudeString");
                            waypoint.longitudeString = (String) tmp.get("longitudeString");
                        }
                    }
                } catch (Exception e) {
                    // failed to parse latitude and/or longitude
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint coordinates");
                }

                j++;
                if (wpItems.length > j) {
                    wp = wpItems[j].split("<td");
                }

                // waypoint note
                try {
                    final Matcher matcherWpNote = patternWpNote.matcher(wp[3]);
                    if (matcherWpNote.find() && matcherWpNote.groupCount() > 0) {
                        waypoint.note = matcherWpNote.group(1).trim();
                    }
                } catch (Exception e) {
                    // failed to parse note
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint note");
                }

                if (cache.waypoints == null) {
                    cache.waypoints = new ArrayList<cgWaypoint>();
                }
                cache.waypoints.add(waypoint);
            }
        }
    }

    if (cache.coords != null) {
        cache.elevation = getElevation(cache.coords);
    }

    final cgRating rating = getRating(cache.guid, cache.geocode);
    if (rating != null) {
        cache.rating = rating.rating;
        cache.votes = rating.votes;
        cache.myVote = rating.myVote;
    }

    cache.updated = System.currentTimeMillis();
    cache.detailedUpdate = System.currentTimeMillis();
    cache.detailed = true;
    caches.cacheList.add(cache);

    return caches;
}

From source file:cgeo.geocaching.connector.gc.GCParser.java

/**
 * Parse a trackable HTML description into a Trackable object
 *
 * @param page// w w  w.java 2  s  . c o  m
 *            the HTML page to parse, already processed through {@link TextUtils#replaceWhitespace}
 * @return the parsed trackable, or null if none could be parsed
 */
static Trackable parseTrackable(final String page, final String possibleTrackingcode) {
    if (StringUtils.isBlank(page)) {
        Log.e("GCParser.parseTrackable: No page given");
        return null;
    }

    if (page.contains(GCConstants.ERROR_TB_DOES_NOT_EXIST)
            || page.contains(GCConstants.ERROR_TB_ARITHMETIC_OVERFLOW)
            || page.contains(GCConstants.ERROR_TB_ELEMENT_EXCEPTION)) {
        return null;
    }

    final Trackable trackable = new Trackable();

    // trackable geocode
    trackable.setGeocode(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true,
            StringUtils.upperCase(possibleTrackingcode)));
    if (trackable.getGeocode() == null) {
        Log.e("GCParser.parseTrackable: could not figure out trackable geocode");
        return null;
    }

    // trackable id
    trackable.setGuid(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid()));

    // trackable icon
    trackable.setIconUrl(
            TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ICON, true, trackable.getIconUrl()));

    // trackable name
    trackable.setName(
            Html.fromHtml(TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_NAME, true, "")).toString());

    // trackable type
    if (StringUtils.isNotBlank(trackable.getName())) {
        trackable.setType(
                TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_TYPE, true, trackable.getType()));
    }

    // trackable owner name
    try {
        final MatcherWrapper matcherOwner = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_OWNER, page);
        if (matcherOwner.find() && matcherOwner.groupCount() > 0) {
            trackable.setOwnerGuid(matcherOwner.group(1));
            trackable.setOwner(matcherOwner.group(2).trim());
        }
    } catch (final RuntimeException e) {
        // failed to parse trackable owner name
        Log.w("GCParser.parseTrackable: Failed to parse trackable owner name");
    }

    // trackable origin
    trackable.setOrigin(
            TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_ORIGIN, true, trackable.getOrigin()));

    // trackable spotted
    try {
        final MatcherWrapper matcherSpottedCache = new MatcherWrapper(
                GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE, page);
        if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) {
            trackable.setSpottedGuid(matcherSpottedCache.group(1));
            trackable.setSpottedName(matcherSpottedCache.group(2).trim());
            trackable.setSpottedType(Trackable.SPOTTED_CACHE);
        }

        final MatcherWrapper matcherSpottedUser = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER,
                page);
        if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) {
            trackable.setSpottedGuid(matcherSpottedUser.group(1));
            trackable.setSpottedName(matcherSpottedUser.group(2).trim());
            trackable.setSpottedType(Trackable.SPOTTED_USER);
        }

        if (TextUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) {
            trackable.setSpottedType(Trackable.SPOTTED_UNKNOWN);
        }

        if (TextUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) {
            trackable.setSpottedType(Trackable.SPOTTED_OWNER);
        }
    } catch (final RuntimeException e) {
        // failed to parse trackable last known place
        Log.w("GCParser.parseTrackable: Failed to parse trackable last known place");
    }

    // released date - can be missing on the page
    final String releaseString = TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_RELEASES, false, null);
    if (releaseString != null) {
        try {
            trackable.setReleased(dateTbIn1.parse(releaseString));
        } catch (ParseException e) {
            if (trackable.getReleased() == null) {
                try {
                    trackable.setReleased(dateTbIn2.parse(releaseString));
                } catch (ParseException e1) {
                    Log.e("Could not parse trackable release " + releaseString);
                }
            }
        }
    }

    // trackable distance
    final String distance = TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null);
    if (null != distance) {
        try {
            trackable.setDistance(DistanceParser.parseDistance(distance, !Settings.isUseImperialUnits()));
        } catch (final NumberFormatException e) {
            Log.e("GCParser.parseTrackable: Failed to parse distance", e);
        }
    }

    // trackable goal
    trackable.setGoal(convertLinks(
            TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GOAL, true, trackable.getGoal())));

    // trackable details & image
    try {
        final MatcherWrapper matcherDetailsImage = new MatcherWrapper(
                GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE, page);
        if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) {
            final String image = StringUtils.trim(matcherDetailsImage.group(3));
            final String details = StringUtils.trim(matcherDetailsImage.group(4));

            if (StringUtils.isNotEmpty(image)) {
                trackable.setImage(image);
            }
            if (StringUtils.isNotEmpty(details)
                    && !StringUtils.equals(details, "No additional details available.")) {
                trackable.setDetails(convertLinks(details));
            }
        }
    } catch (final RuntimeException e) {
        // failed to parse trackable details & image
        Log.w("GCParser.parseTrackable: Failed to parse trackable details & image");
    }
    if (StringUtils.isEmpty(trackable.getDetails()) && page.contains(GCConstants.ERROR_TB_NOT_ACTIVATED)) {
        trackable.setDetails(CgeoApplication.getInstance().getString(R.string.trackable_not_activated));
    }

    // trackable logs
    try {
        final MatcherWrapper matcherLogs = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG, page);
        /*
         * 1. Type (image)
         * 2. Date
         * 3. Author
         * 4. Cache-GUID
         * 5. <ignored> (strike-through property for ancient caches)
         * 6. Cache-name
         * 7. Log text
         */
        while (matcherLogs.find()) {
            long date = 0;
            try {
                date = GCLogin.parseGcCustomDate(matcherLogs.group(2)).getTime();
            } catch (final ParseException e) {
            }

            final LogEntry logDone = new LogEntry(Html.fromHtml(matcherLogs.group(3)).toString().trim(), date,
                    LogType.getByIconName(matcherLogs.group(1)), matcherLogs.group(7).trim());

            if (matcherLogs.group(4) != null && matcherLogs.group(6) != null) {
                logDone.cacheGuid = matcherLogs.group(4);
                logDone.cacheName = matcherLogs.group(6);
            }

            // Apply the pattern for images in a trackable log entry against each full log (group(0))
            final String logEntry = matcherLogs.group(0);
            final MatcherWrapper matcherLogImages = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG_IMAGES,
                    logEntry);
            /*
             * 1. Image URL
             * 2. Image title
             */
            while (matcherLogImages.find()) {
                final Image logImage = new Image(matcherLogImages.group(1), matcherLogImages.group(2));
                logDone.addLogImage(logImage);
            }

            trackable.getLogs().add(logDone);
        }
    } catch (final Exception e) {
        // failed to parse logs
        Log.w("GCParser.parseCache: Failed to parse cache logs", e);
    }

    // tracking code
    if (!StringUtils.equalsIgnoreCase(trackable.getGeocode(), possibleTrackingcode)) {
        trackable.setTrackingcode(possibleTrackingcode);
    }

    if (CgeoApplication.getInstance() != null) {
        DataStore.saveTrackable(trackable);
    }

    return trackable;
}

From source file:carnero.cgeo.cgBase.java

public cgCacheWrap parseCache(String page, int reason) {
    if (page == null || page.length() == 0) {
        Log.e(cgSettings.tag, "cgeoBase.parseCache: No page given");
        return null;
    }/*from  w  w  w  . j av  a 2  s.co m*/

    final Pattern patternGeocode = Pattern.compile(
            "<meta name=\"og:url\" content=\"[^\"]+/(GC[0-9A-Z]+)\"[^>]*>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternCacheId = Pattern.compile("/seek/log\\.aspx\\?ID=(\\d+)",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternCacheGuid = Pattern.compile(
            "<link rel=\"alternate\" href=\"[^\"]*/datastore/rss_galleryimages\\.ashx\\?guid=([0-9a-z\\-]+)\"[^>]*>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternType = Pattern.compile(
            "<img src=\"[^\"]*/WptTypes/\\d+\\.gif\" alt=\"([^\"]+)\" (title=\"[^\"]*\" )?width=\"32\" height=\"32\"[^>]*>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

    final Pattern patternName = Pattern.compile(
            "<h2[^>]*>[^<]*<span id=\"ctl00_ContentBody_CacheName\">([^<]+)<\\/span>[^<]*<\\/h2>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternSize = Pattern.compile(
            "<div class=\"CacheSize[^\"]*\">[^<]*<p[^>]*>[^S]*Size[^:]*:[^<]*<span[^>]*>[^<]*<img src=\"[^\"]*/icons/container/[a-z_]+\\.gif\" alt=\"Size: ([^\"]+)\"[^>]*>[^<]*<small>[^<]*</small>[^<]*</span>[^<]*</p>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternDifficulty = Pattern.compile(
            "<span id=\"ctl00_ContentBody_uxLegendScale\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\" alt=\"[^\"]+\"[^>]*>[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternTerrain = Pattern.compile(
            "<span id=\"ctl00_ContentBody_Localize6\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\" alt=\"[^\"]+\"[^>]*>[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternOwner = Pattern.compile(
            "<span class=\"minorCacheDetails\">[^\\w]*An?([^\\w]*Event)?[^\\w]*cache[^\\w]*by[^<]*<a href=\"[^\"]+\">([^<]+)</a>[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternOwnerReal = Pattern.compile(
            "<a id=\"ctl00_ContentBody_uxFindLinksHiddenByThisUser\" href=\"[^\"]*/seek/nearest\\.aspx\\?u=*([^\"]+)\">[^<]+</a>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternHidden = Pattern.compile(
            "<span[^>]*>[^\\w]*Hidden[^:]*:[^\\d]*((\\d+)\\/(\\d+)\\/(\\d+))[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternHiddenEvent = Pattern.compile(
            "<span[^>]*>[^\\w]*Event[^\\w]*Date[^:]*:[^\\w]*[a-zA-Z]+,[^\\d]*((\\d+)[^\\w]*(\\w+)[^\\d]*(\\d+))[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternFavourite = Pattern.compile(
            "<a id=\"uxFavContainerLink\"[^>]*>[^<]*<div[^<]*<span class=\"favorite-value\">[^\\d]*([0-9]+)[^\\d^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

    final Pattern patternFound = Pattern.compile(
            "<p>[^<]*<a id=\"ctl00_ContentBody_hlFoundItLog\"[^<]*<img src=\".*/images/stockholm/16x16/check\\.gif\"[^>]*>[^<]*</a>[^<]*</p>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternLatLon = Pattern.compile(
            "<span id=\"ctl00_ContentBody_LatLon\"[^>]*>(<b>)?([^<]*)(<\\/b>)?<\\/span>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternLocation = Pattern.compile("<span id=\"ctl00_ContentBody_Location\"[^>]*>In ([^<]*)",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternHint = Pattern.compile(
            "<p>([^<]*<strong>)?[^\\w]*Additional Hints([^<]*<\\/strong>)?[^\\(]*\\(<a[^>]+>Encrypt</a>\\)[^<]*<\\/p>[^<]*<div id=\"div_hint\"[^>]*>(.*)</div>[^<]*<div id=[\\'|\"]dk[\\'|\"]",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternDescShort = Pattern.compile(
            "<div class=\"UserSuppliedContent\">[^<]*<span id=\"ctl00_ContentBody_ShortDescription\"[^>]*>((?:(?!</span>[^\\w^<]*</div>).)*)</span>[^\\w^<]*</div>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternDesc = Pattern.compile(
            "<div class=\"UserSuppliedContent\">[^<]*<span id=\"ctl00_ContentBody_LongDescription\"[^>]*>((?:(?!</span>[^\\w^<]*</div>).)*)</span>[^<]*</div>[^<]*<p>[^<]*</p>[^<]*<p>[^<]*<strong>[^\\w]*Additional Hints</strong>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternCountLogs = Pattern.compile(
            "<span id=\"ctl00_ContentBody_lblFindCounts\"><p>(.*)<\\/p><\\/span>", Pattern.CASE_INSENSITIVE);
    final Pattern patternCountLog = Pattern.compile(
            " src=\"\\/images\\/icons\\/([^\\.]*).gif\" alt=\"[^\"]*\" title=\"[^\"]*\" />([0-9]*)[^0-9]+",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternLogs = Pattern.compile(
            "<table class=\"LogsTable[^\"]*\"[^>]*>[^<]*<tr>(.*)</tr>[^<]*</table>[^<]*<p",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternLog = Pattern.compile(
            "<td[^>]*>[^<]*<strong>[^<]*<img src=\"[^\"]*/images/icons/([^\\.]+)\\.[a-z]{2,5}\"[^>]*>&nbsp;([a-zA-Z]+) (\\d+)(, (\\d+))? by <a href=[^>]+>([^<]+)</a>[<^]*</strong>([^\\(]*\\((\\d+) found\\))?(<br[^>]*>)+((?:(?!<small>).)*)(<br[^>]*>)+<small>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternAttributes = Pattern.compile(
            "<h3 class=\"WidgetHeader\">[^<]*<img[^>]+>[^\\w]*Attributes[^<]*</h3>[^<]*<div class=\"WidgetBody\">(([^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+)[^<]*<p",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternAttributesInside = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+)\"[^>]*>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternSpoilers = Pattern.compile(
            "<span id=\"ctl00_ContentBody_Images\">((<a href=\"[^\"]+\"[^>]*>[^<]*<img[^>]+>[^<]*<span>[^>]+</span>[^<]*</a>[^<]*<br[^>]*>([^<]*(<br[^>]*>)+)?)+)[^<]*</span>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternSpoilersInside = Pattern.compile(
            "[^<]*<a href=\"([^\"]+)\"[^>]*>[^<]*<img[^>]+>[^<]*<span>([^>]+)</span>[^<]*</a>[^<]*<br[^>]*>(([^<]*)(<br[^<]*>)+)?",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternInventory = Pattern.compile(
            "<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">[^\\w]*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternInventoryInside = Pattern.compile(
            "[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>",
            Pattern.CASE_INSENSITIVE);

    final cgCacheWrap caches = new cgCacheWrap();
    final cgCache cache = new cgCache();

    if (page.indexOf("Cache is Unpublished") > -1) {
        caches.error = "cache was unpublished";
        return caches;
    }

    if (page.indexOf("Sorry, the owner of this listing has made it viewable to Premium Members only.") != -1) {
        caches.error = "requested cache is for premium members only";
        return caches;
    }

    if (page.indexOf("has chosen to make this cache listing visible to Premium Members only.") != -1) {
        caches.error = "requested cache is for premium members only";
        return caches;
    }

    if (page.indexOf("<li>This cache is temporarily unavailable.") != -1) {
        cache.disabled = true;
    } else {
        cache.disabled = false;
    }

    if (page.indexOf("<li>This cache has been archived,") != -1) {
        cache.archived = true;
    } else {
        cache.archived = false;
    }

    if (page.indexOf("<p class=\"Warning\">This is a Premium Member Only cache.</p>") != -1) {
        cache.members = true;
    } else {
        cache.members = false;
    }

    cache.reason = reason;

    // cache geocode
    try {
        final Matcher matcherGeocode = patternGeocode.matcher(page);
        while (matcherGeocode.find()) {
            if (matcherGeocode.groupCount() > 0) {
                cache.geocode = (String) matcherGeocode.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse cache geocode
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache geocode");
    }

    // cache id
    try {
        final Matcher matcherCacheId = patternCacheId.matcher(page);
        while (matcherCacheId.find()) {
            if (matcherCacheId.groupCount() > 0) {
                cache.cacheid = (String) matcherCacheId.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse cache id
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache id");
    }

    // cache guid
    try {
        final Matcher matcherCacheGuid = patternCacheGuid.matcher(page);
        while (matcherCacheGuid.find()) {
            if (matcherCacheGuid.groupCount() > 0) {
                cache.guid = (String) matcherCacheGuid.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse cache guid
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache guid");
    }

    // name
    try {
        final Matcher matcherName = patternName.matcher(page);
        while (matcherName.find()) {
            if (matcherName.groupCount() > 0) {
                cache.name = Html.fromHtml(matcherName.group(1)).toString();
            }
        }
    } catch (Exception e) {
        // failed to parse cache name
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache name");
    }

    // owner real name
    try {
        final Matcher matcherOwnerReal = patternOwnerReal.matcher(page);
        while (matcherOwnerReal.find()) {
            if (matcherOwnerReal.groupCount() > 0) {
                cache.ownerReal = URLDecoder.decode(matcherOwnerReal.group(1));
            }
        }
    } catch (Exception e) {
        // failed to parse owner real name
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache owner real name");
    }

    final String username = settings.getUsername();
    if (cache.ownerReal != null && username != null && cache.ownerReal.equalsIgnoreCase(username)) {
        cache.own = true;
    }

    int pos = -1;
    String tableInside = page;

    pos = tableInside.indexOf("id=\"cacheDetails\"");
    if (pos == -1) {
        Log.e(cgSettings.tag, "cgeoBase.parseCache: ID \"cacheDetails\" not found on page");
        return null;
    }

    tableInside = tableInside.substring(pos);

    pos = tableInside.indexOf("<div class=\"CacheInformationTable\"");
    if (pos == -1) {
        Log.e(cgSettings.tag, "cgeoBase.parseCache: ID \"CacheInformationTable\" not found on page");
        return null;
    }

    tableInside = tableInside.substring(0, pos);

    if (tableInside != null && tableInside.length() > 0) {
        // cache terrain
        try {
            final Matcher matcherTerrain = patternTerrain.matcher(tableInside);
            while (matcherTerrain.find()) {
                if (matcherTerrain.groupCount() > 0) {
                    cache.terrain = new Float(
                            Pattern.compile("_").matcher(matcherTerrain.group(1)).replaceAll("."));
                }
            }
        } catch (Exception e) {
            // failed to parse terrain
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache terrain");
        }

        // cache difficulty
        try {
            final Matcher matcherDifficulty = patternDifficulty.matcher(tableInside);
            while (matcherDifficulty.find()) {
                if (matcherDifficulty.groupCount() > 0) {
                    cache.difficulty = new Float(
                            Pattern.compile("_").matcher(matcherDifficulty.group(1)).replaceAll("."));
                }
            }
        } catch (Exception e) {
            // failed to parse difficulty
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache difficulty");
        }

        // owner
        try {
            final Matcher matcherOwner = patternOwner.matcher(tableInside);
            while (matcherOwner.find()) {
                if (matcherOwner.groupCount() > 0) {
                    cache.owner = Html.fromHtml(matcherOwner.group(2)).toString();
                }
            }
        } catch (Exception e) {
            // failed to parse owner
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache owner");
        }

        // hidden
        try {
            final Matcher matcherHidden = patternHidden.matcher(tableInside);
            while (matcherHidden.find()) {
                if (matcherHidden.groupCount() > 0) {
                    cache.hidden = dateIn.parse(matcherHidden.group(1));
                }
            }
        } catch (Exception e) {
            // failed to parse cache hidden date
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache hidden date");
        }

        if (cache.hidden == null) {
            // event date
            try {
                final Matcher matcherHiddenEvent = patternHiddenEvent.matcher(tableInside);
                while (matcherHiddenEvent.find()) {
                    if (matcherHiddenEvent.groupCount() > 0) {
                        cache.hidden = dateEvIn.parse(matcherHiddenEvent.group(1));
                    }
                }
            } catch (Exception e) {
                // failed to parse cache event date
                Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache event date");
            }
        }

        // favourite
        try {
            final Matcher matcherFavourite = patternFavourite.matcher(tableInside);
            while (matcherFavourite.find()) {
                if (matcherFavourite.groupCount() > 0) {
                    cache.favouriteCnt = Integer.parseInt(matcherFavourite.group(1));
                }
            }
        } catch (Exception e) {
            // failed to parse favourite count
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse favourite count");
        }

        // cache size
        try {
            final Matcher matcherSize = patternSize.matcher(tableInside);
            while (matcherSize.find()) {
                if (matcherSize.groupCount() > 0) {
                    cache.size = matcherSize.group(1).toLowerCase();
                }
            }
        } catch (Exception e) {
            // failed to parse size
            Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache size");
        }
    }

    // cache found
    try {
        final Matcher matcherFound = patternFound.matcher(page);
        while (matcherFound.find()) {
            if (matcherFound.group() != null && matcherFound.group().length() > 0) {
                cache.found = true;
            }
        }
    } catch (Exception e) {
        // failed to parse found
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse found");
    }

    // cache type
    try {
        final Matcher matcherType = patternType.matcher(page);
        while (matcherType.find()) {
            if (matcherType.groupCount() > 0) {
                cache.type = cacheTypes.get(matcherType.group(1).toLowerCase());
            }
        }
    } catch (Exception e) {
        // failed to parse type
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache type");
    }

    // latitude and logitude
    try {
        final Matcher matcherLatLon = patternLatLon.matcher(page);
        while (matcherLatLon.find()) {
            if (matcherLatLon.groupCount() > 0) {
                cache.latlon = matcherLatLon.group(2); // first is <b>

                HashMap<String, Object> tmp = this.parseLatlon(cache.latlon);
                if (tmp.size() > 0) {
                    cache.latitude = (Double) tmp.get("latitude");
                    cache.longitude = (Double) tmp.get("longitude");
                    cache.latitudeString = (String) tmp.get("latitudeString");
                    cache.longitudeString = (String) tmp.get("longitudeString");
                    cache.reliableLatLon = true;
                }
                tmp = null;
            }
        }
    } catch (Exception e) {
        // failed to parse latitude and/or longitude
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache coordinates");
    }

    // cache location
    try {
        final Matcher matcherLocation = patternLocation.matcher(page);
        while (matcherLocation.find()) {
            if (matcherLocation.groupCount() > 0) {
                cache.location = matcherLocation.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse location
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache location");
    }

    // cache hint
    try {
        final Matcher matcherHint = patternHint.matcher(page);
        while (matcherHint.find()) {
            if (matcherHint.groupCount() > 2 && matcherHint.group(3) != null) {
                // replace linebreak and paragraph tags
                String hint = Pattern.compile("<(br|p)[^>]*>").matcher(matcherHint.group(3)).replaceAll("\n");
                if (hint != null) {
                    cache.hint = hint.replaceAll(Pattern.quote("</p>"), "").trim();
                }
            }
        }
    } catch (Exception e) {
        // failed to parse hint
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache hint");
    }

    /*
    // short info debug
    Log.d(cgSettings.tag, "gc-code: " + cache.geocode);
    Log.d(cgSettings.tag, "id: " + cache.cacheid);
    Log.d(cgSettings.tag, "guid: " + cache.guid);
    Log.d(cgSettings.tag, "name: " + cache.name);
    Log.d(cgSettings.tag, "terrain: " + cache.terrain);
    Log.d(cgSettings.tag, "difficulty: " + cache.difficulty);
    Log.d(cgSettings.tag, "owner: " + cache.owner);
    Log.d(cgSettings.tag, "owner (real): " + cache.ownerReal);
    Log.d(cgSettings.tag, "hidden: " + dateOutShort.format(cache.hidden));
    Log.d(cgSettings.tag, "favorite: " + cache.favouriteCnt);
    Log.d(cgSettings.tag, "size: " + cache.size);
    if (cache.found) {
       Log.d(cgSettings.tag, "found!");
    } else {
       Log.d(cgSettings.tag, "not found");
    }
    Log.d(cgSettings.tag, "type: " + cache.type);
    Log.d(cgSettings.tag, "latitude: " + String.format("%.6f", cache.latitude));
    Log.d(cgSettings.tag, "longitude: " + String.format("%.6f", cache.longitude));
    Log.d(cgSettings.tag, "location: " + cache.location);
    Log.d(cgSettings.tag, "hint: " + cache.hint);
    */

    // cache short description
    try {
        final Matcher matcherDescShort = patternDescShort.matcher(page);
        while (matcherDescShort.find()) {
            if (matcherDescShort.groupCount() > 0) {
                cache.shortdesc = matcherDescShort.group(1).trim();
            }
        }
    } catch (Exception e) {
        // failed to parse short description
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache short description");
    }

    // cache description
    try {
        final Matcher matcherDesc = patternDesc.matcher(page);
        while (matcherDesc.find()) {
            if (matcherDesc.groupCount() > 0) {
                cache.description = matcherDesc.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse short description
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache description");
    }

    // cache attributes
    try {
        final Matcher matcherAttributes = patternAttributes.matcher(page);
        while (matcherAttributes.find()) {
            if (matcherAttributes.groupCount() > 0) {
                final String attributesPre = matcherAttributes.group(1);
                final Matcher matcherAttributesInside = patternAttributesInside.matcher(attributesPre);

                while (matcherAttributesInside.find()) {
                    if (matcherAttributesInside.groupCount() > 1
                            && matcherAttributesInside.group(2).equalsIgnoreCase("blank") != true) {
                        if (cache.attributes == null) {
                            cache.attributes = new ArrayList<String>();
                        }
                        // by default, use the tooltip of the attribute
                        String attribute = matcherAttributesInside.group(2).toLowerCase();

                        // if the image name can be recognized, use the image name as attribute
                        String imageName = matcherAttributesInside.group(1).trim();
                        if (imageName.length() > 0) {
                            int start = imageName.lastIndexOf('/');
                            int end = imageName.lastIndexOf('.');
                            if (start >= 0 && end >= 0) {
                                attribute = imageName.substring(start + 1, end).replace('-', '_');
                            }
                        }
                        cache.attributes.add(attribute);
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache attributes
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache attributes");
    }

    // cache spoilers
    try {
        final Matcher matcherSpoilers = patternSpoilers.matcher(page);
        while (matcherSpoilers.find()) {
            if (matcherSpoilers.groupCount() > 0) {
                final String spoilersPre = matcherSpoilers.group(1);
                final Matcher matcherSpoilersInside = patternSpoilersInside.matcher(spoilersPre);

                while (matcherSpoilersInside.find()) {
                    if (matcherSpoilersInside.groupCount() > 0) {
                        final cgSpoiler spoiler = new cgSpoiler();
                        spoiler.url = matcherSpoilersInside.group(1);

                        if (matcherSpoilersInside.group(2) != null) {
                            spoiler.title = matcherSpoilersInside.group(2);
                        }
                        if (matcherSpoilersInside.group(4) != null) {
                            spoiler.description = matcherSpoilersInside.group(4);
                        }

                        if (cache.spoilers == null) {
                            cache.spoilers = new ArrayList<cgSpoiler>();
                        }
                        cache.spoilers.add(spoiler);
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache spoilers
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache spoilers");
    }

    // cache inventory
    try {
        cache.inventoryItems = 0;

        final Matcher matcherInventory = patternInventory.matcher(page);
        while (matcherInventory.find()) {
            if (cache.inventory == null) {
                cache.inventory = new ArrayList<cgTrackable>();
            }

            if (matcherInventory.groupCount() > 1) {
                final String inventoryPre = matcherInventory.group(2);

                if (inventoryPre != null && inventoryPre.length() > 0) {
                    final Matcher matcherInventoryInside = patternInventoryInside.matcher(inventoryPre);

                    while (matcherInventoryInside.find()) {
                        if (matcherInventoryInside.groupCount() > 0) {
                            final cgTrackable inventoryItem = new cgTrackable();
                            inventoryItem.guid = matcherInventoryInside.group(1);
                            inventoryItem.name = matcherInventoryInside.group(2);

                            cache.inventory.add(inventoryItem);
                            cache.inventoryItems++;
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache inventory
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache inventory (2)");
    }

    // cache logs counts
    try {
        final Matcher matcherLogCounts = patternCountLogs.matcher(page);
        while (matcherLogCounts.find()) {
            if (matcherLogCounts.groupCount() > 0) {
                final String[] logs = matcherLogCounts.group(1).split("<img");
                final int logsCnt = logs.length;

                for (int k = 1; k < logsCnt; k++) {
                    Integer type = null;
                    Integer count = null;
                    final Matcher matcherLog = patternCountLog.matcher(logs[k]);

                    if (matcherLog.find()) {
                        String typeStr = matcherLog.group(1);
                        String countStr = matcherLog.group(2);
                        if (typeStr != null && typeStr.length() > 0) {
                            if (logTypes.containsKey(typeStr.toLowerCase()) == true) {
                                type = logTypes.get(typeStr.toLowerCase());
                            }
                        }
                        if (countStr != null && countStr.length() > 0) {
                            count = Integer.parseInt(countStr);
                        }
                        if (type != null && count != null) {
                            cache.logCounts.put(type, count);
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse logs
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache log count");
    }

    // cache logs
    try {
        final Matcher matcherLogs = patternLogs.matcher(page);
        while (matcherLogs.find()) {
            if (matcherLogs.groupCount() > 0) {
                final String[] logs = matcherLogs.group(1).split("</tr><tr>");
                final int logsCnt = logs.length;

                for (int k = 0; k < logsCnt; k++) {
                    final Matcher matcherLog = patternLog.matcher(logs[k]);

                    if (matcherLog.find()) {
                        final cgLog logDone = new cgLog();

                        String logTmp = matcherLog.group(10);

                        int day = -1;
                        try {
                            day = Integer.parseInt(matcherLog.group(3));
                        } catch (Exception e) {
                            Log.w(cgSettings.tag, "Failed to parse logs date (day): " + e.toString());
                        }

                        int month = -1;
                        // January  | February  | March  | April  | May | June | July | August  | September | October  | November  | December
                        if (matcherLog.group(2).equalsIgnoreCase("January")) {
                            month = 0;
                        } else if (matcherLog.group(2).equalsIgnoreCase("February")) {
                            month = 1;
                        } else if (matcherLog.group(2).equalsIgnoreCase("March")) {
                            month = 2;
                        } else if (matcherLog.group(2).equalsIgnoreCase("April")) {
                            month = 3;
                        } else if (matcherLog.group(2).equalsIgnoreCase("May")) {
                            month = 4;
                        } else if (matcherLog.group(2).equalsIgnoreCase("June")) {
                            month = 5;
                        } else if (matcherLog.group(2).equalsIgnoreCase("July")) {
                            month = 6;
                        } else if (matcherLog.group(2).equalsIgnoreCase("August")) {
                            month = 7;
                        } else if (matcherLog.group(2).equalsIgnoreCase("September")) {
                            month = 8;
                        } else if (matcherLog.group(2).equalsIgnoreCase("October")) {
                            month = 9;
                        } else if (matcherLog.group(2).equalsIgnoreCase("November")) {
                            month = 10;
                        } else if (matcherLog.group(2).equalsIgnoreCase("December")) {
                            month = 11;
                        } else {
                            Log.w(cgSettings.tag, "Failed to parse logs date (month).");
                        }

                        int year = -1;
                        final String yearPre = matcherLog.group(5);

                        if (yearPre == null) {
                            Calendar date = Calendar.getInstance();
                            year = date.get(Calendar.YEAR);
                        } else {
                            try {
                                year = Integer.parseInt(matcherLog.group(5));
                            } catch (Exception e) {
                                Log.w(cgSettings.tag, "Failed to parse logs date (year): " + e.toString());
                            }
                        }

                        long logDate;
                        if (year > 0 && month >= 0 && day > 0) {
                            Calendar date = Calendar.getInstance();
                            date.set(year, month, day, 12, 0, 0);
                            logDate = date.getTimeInMillis();
                            logDate = (long) (Math.ceil(logDate / 1000)) * 1000;
                        } else {
                            logDate = 0;
                        }

                        if (logTypes.containsKey(matcherLog.group(1).toLowerCase()) == true) {
                            logDone.type = logTypes.get(matcherLog.group(1).toLowerCase());
                        } else {
                            logDone.type = logTypes.get("icon_note");
                        }

                        logDone.author = Html.fromHtml(matcherLog.group(6)).toString();
                        logDone.date = logDate;
                        if (matcherLog.group(8) != null) {
                            logDone.found = new Integer(matcherLog.group(8));
                        }
                        logDone.log = logTmp;

                        if (cache.logs == null) {
                            cache.logs = new ArrayList<cgLog>();
                        }
                        cache.logs.add(logDone);
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse logs
        Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse cache logs");
    }

    int wpBegin = 0;
    int wpEnd = 0;

    wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
    if (wpBegin != -1) { // parse waypoints
        final Pattern patternWpType = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg",
                Pattern.CASE_INSENSITIVE);
        final Pattern patternWpPrefixOrLookupOrLatlon = Pattern
                .compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>", Pattern.CASE_INSENSITIVE);
        final Pattern patternWpName = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>", Pattern.CASE_INSENSITIVE);
        final Pattern patternWpNote = Pattern.compile("colspan=\"6\">(.*)<\\/td>", Pattern.CASE_INSENSITIVE);

        String wpList = page.substring(wpBegin);

        wpEnd = wpList.indexOf("</p>");
        if (wpEnd > -1 && wpEnd <= wpList.length()) {
            wpList = wpList.substring(0, wpEnd);
        }

        if (wpList.indexOf("No additional waypoints to display.") == -1) {
            wpEnd = wpList.indexOf("</table>");
            wpList = wpList.substring(0, wpEnd);

            wpBegin = wpList.indexOf("<tbody>");
            wpEnd = wpList.indexOf("</tbody>");
            if (wpBegin >= 0 && wpEnd >= 0 && wpEnd <= wpList.length()) {
                wpList = wpList.substring(wpBegin + 7, wpEnd);
            }

            final String[] wpItems = wpList.split("<tr");

            String[] wp;
            for (int j = 1; j < wpItems.length; j++) {
                final cgWaypoint waypoint = new cgWaypoint();

                wp = wpItems[j].split("<td");

                // waypoint type
                try {
                    final Matcher matcherWpType = patternWpType.matcher(wp[3]);
                    while (matcherWpType.find()) {
                        if (matcherWpType.groupCount() > 0) {
                            waypoint.type = matcherWpType.group(1);
                            if (waypoint.type != null) {
                                waypoint.type = waypoint.type.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse type
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint type");
                }

                // waypoint prefix
                try {
                    final Matcher matcherWpPrefix = patternWpPrefixOrLookupOrLatlon.matcher(wp[4]);
                    while (matcherWpPrefix.find()) {
                        if (matcherWpPrefix.groupCount() > 1) {
                            waypoint.prefix = matcherWpPrefix.group(2);
                            if (waypoint.prefix != null) {
                                waypoint.prefix = waypoint.prefix.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse prefix
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint prefix");
                }

                // waypoint lookup
                try {
                    final Matcher matcherWpLookup = patternWpPrefixOrLookupOrLatlon.matcher(wp[5]);
                    while (matcherWpLookup.find()) {
                        if (matcherWpLookup.groupCount() > 1) {
                            waypoint.lookup = matcherWpLookup.group(2);
                            if (waypoint.lookup != null) {
                                waypoint.lookup = waypoint.lookup.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse lookup
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint lookup");
                }

                // waypoint name
                try {
                    final Matcher matcherWpName = patternWpName.matcher(wp[6]);
                    while (matcherWpName.find()) {
                        if (matcherWpName.groupCount() > 0) {
                            waypoint.name = matcherWpName.group(1);
                            if (waypoint.name != null) {
                                waypoint.name = waypoint.name.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse name
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint name");
                }

                // waypoint latitude and logitude
                try {
                    final Matcher matcherWpLatLon = patternWpPrefixOrLookupOrLatlon.matcher(wp[7]);
                    while (matcherWpLatLon.find()) {
                        if (matcherWpLatLon.groupCount() > 1) {
                            waypoint.latlon = Html.fromHtml(matcherWpLatLon.group(2)).toString();

                            final HashMap<String, Object> tmp = this.parseLatlon(waypoint.latlon);
                            if (tmp.size() > 0) {
                                waypoint.latitude = (Double) tmp.get("latitude");
                                waypoint.longitude = (Double) tmp.get("longitude");
                                waypoint.latitudeString = (String) tmp.get("latitudeString");
                                waypoint.longitudeString = (String) tmp.get("longitudeString");
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse latitude and/or longitude
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint coordinates");
                }

                j++;
                if (wpItems.length > j) {
                    wp = wpItems[j].split("<td");
                }

                // waypoint note
                try {
                    final Matcher matcherWpNote = patternWpNote.matcher(wp[3]);
                    while (matcherWpNote.find()) {
                        if (matcherWpNote.groupCount() > 0) {
                            waypoint.note = matcherWpNote.group(1);
                            if (waypoint.note != null) {
                                waypoint.note = waypoint.note.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse note
                    Log.w(cgSettings.tag, "cgeoBase.parseCache: Failed to parse waypoint note");
                }

                if (cache.waypoints == null)
                    cache.waypoints = new ArrayList<cgWaypoint>();
                cache.waypoints.add(waypoint);
            }
        }
    }

    if (cache.latitude != null && cache.longitude != null) {
        cache.elevation = getElevation(cache.latitude, cache.longitude);
    }

    final cgRating rating = getRating(cache.guid, cache.geocode);
    if (rating != null) {
        cache.rating = rating.rating;
        cache.votes = rating.votes;
        cache.myVote = rating.myVote;
    }

    cache.updated = System.currentTimeMillis();
    cache.detailedUpdate = System.currentTimeMillis();
    cache.detailed = true;
    caches.cacheList.add(cache);

    return caches;
}

From source file:cl.ipp.katbag.fragment.Develop.java

public void setControl(String title, final String humanTextRow, final int dialogIdObjectItemList,
        final long object_id) {
    int resource = 0;
    View dialog_layout = null;/*from  w  w w.  j a  va  2  s  .  c  om*/
    resource = getResources().getIdentifier("dialog_control_" + dialogIdObjectItemList, "layout",
            mainActivity.getPackageName());
    LayoutInflater inflater = LayoutInflater.from(mainActivity.context);
    dialog_layout = inflater.inflate(resource, null);

    if (object_id != -1) {
        dev.clear();
        dev = mainActivity.katbagHandler.selectDevelopForId(object_id);
    }

    switch (dialogIdObjectItemList) {
    case 0:
        editN = (EditText) dialog_layout.findViewById(R.id.dialog_n);

        if (object_id == -1) {
            editN.setText(getString(R.string.develop_edittext_number_default_value));
        } else {
            editN.setText(dev.get(3));
        }

        editN.setSelection(editN.getText().length());

        break;

    case 1:
        editN = (EditText) dialog_layout.findViewById(R.id.dialog_n);

        if (object_id == -1) {
            editN.setText(getString(R.string.develop_edittext_number_default_value));
        } else {
            editN.setText(dev.get(3));
        }

        editN.setSelection(editN.getText().length());

        break;

    case 2:
        editN = (EditText) dialog_layout.findViewById(R.id.dialog_n);

        if (object_id == -1) {
            editN.setText(getString(R.string.develop_edittext_number_default_value));
        } else {
            editN.setText(dev.get(3));
        }

        editN.setSelection(editN.getText().length());

        break;

    case 3:
        editN = (EditText) dialog_layout.findViewById(R.id.dialog_n);

        if (object_id == -1) {
            editN.setText(getString(R.string.develop_edittext_number_default_value));
        } else {
            editN.setText(dev.get(3));
        }

        editN.setSelection(editN.getText().length());

        break;

    case 4:
        editN = (EditText) dialog_layout.findViewById(R.id.dialog_n);

        if (object_id == -1) {
            editN.setText(getString(R.string.develop_edittext_number_default_value));
        } else {
            editN.setText(dev.get(3));
        }

        editN.setSelection(editN.getText().length());

        break;

    case 5:
        editN = (EditText) dialog_layout.findViewById(R.id.dialog_message);

        if (object_id == -1) {
            editN.setText(getString(R.string.develop_edittext_number_default_string));
        } else {
            editN.setText(dev.get(3));
        }

        editN.setSelection(editN.getText().length());

        break;

    case 6:
        editN = (EditText) dialog_layout.findViewById(R.id.dialog_n);

        if (object_id == -1) {
            editN.setText(getString(R.string.develop_edittext_number_default_value));
        } else {
            editN.setText(dev.get(3));
        }

        editN.setSelection(editN.getText().length());

        break;

    }

    AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity.context);
    builder.setView(dialog_layout);
    builder.setTitle(Html.fromHtml(title));
    builder.setNegativeButton(getString(R.string.dialog_button_cancel), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            // :)
        }
    });

    builder.setPositiveButton(getString(R.string.dialog_button_ok), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            switch (dialogIdObjectItemList) {
            case 0:
                // validate field
                if (editN.getText().toString().contentEquals("")) {
                    KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_empty_n));
                    return;
                }

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "");
                }
                break;

            case 1:
                // validate field
                if (editN.getText().toString().contentEquals("")) {
                    KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_empty_n));
                    return;
                }

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "");
                }
                break;

            case 2:
                // validate field
                if (editN.getText().toString().contentEquals("")) {
                    KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_empty_n));
                    return;
                }

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "");
                }

                break;

            case 3:
                // validate field
                if (editN.getText().toString().contentEquals("")) {
                    KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_empty_n));
                    return;
                }

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "");
                }

                break;

            case 4:
                // validate field
                if (editN.getText().toString().contentEquals("")) {
                    KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_empty_n));
                    return;
                }

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "");
                }

                break;

            case 5:
                // validate field
                if (editN.getText().toString().contentEquals("")) {
                    KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_empty_n));
                    return;
                }

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "");
                }

                break;

            case 6:
                // validate field
                if (editN.getText().toString().contentEquals("")) {
                    KatbagUtilities.message(mainActivity.context, getString(R.string.develop_message_empty_n));
                    return;
                }

                if (object_id == -1) {
                    mainActivity.katbagHandler.insertDevelop(id_app, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "", 0, 0);
                } else {
                    mainActivity.katbagHandler.updateDevelop(object_id, "control",
                            String.format(humanTextRow, editN.getText().toString()), // row text
                            String.valueOf(dialogIdObjectItemList), // first parameter is the type control
                            editN.getText().toString(), // n
                            "", "", "", "", "", "");
                }

                break;

            }

            loadListView();
        }
    });

    builder.show();
}

From source file:carnero.cgeo.original.libs.Base.java

public CacheWrap parseCache(String page, int reason) {
    if (page == null || page.length() == 0) {
        Log.e(Settings.tag, "cgeoBase.parseCache: No page given");
        return null;
    }/*  ww  w . jav  a 2 s  .  c  o m*/

    final Pattern patternGeocode = Pattern.compile(
            "<meta name=\"og:url\" content=\"[^\"]+/(GC[0-9A-Z]+)\"[^>]*>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternCacheId = Pattern.compile("/seek/log\\.aspx\\?ID=(\\d+)",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternCacheGuid = Pattern.compile(
            "<link rel=\"alternate\" href=\"[^\"]*/datastore/rss_galleryimages\\.ashx\\?guid=([0-9a-z\\-]+)\"[^>]*>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternType = Pattern.compile(
            "<img src=\"[^\"]*/WptTypes/\\d+\\.gif\" alt=\"([^\"]+)\" (title=\"[^\"]*\" )?width=\"32\" height=\"32\"[^>]*>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

    final Pattern patternName = Pattern.compile(
            "<h2[^>]*>[^<]*<span id=\"ctl00_ContentBody_CacheName\">([^<]+)<\\/span>[^<]*<\\/h2>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternSize = Pattern.compile(
            "<div class=\"CacheSize[^\"]*\">[^<]*<p[^>]*>[^S]*Size[^:]*:[^<]*<span[^>]*>[^<]*<img src=\"[^\"]*/icons/container/[a-z_]+\\.gif\" alt=\"Size: ([^\"]+)\"[^>]*>[^<]*<small>[^<]*</small>[^<]*</span>[^<]*</p>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternDifficulty = Pattern.compile(
            "<span id=\"ctl00_ContentBody_uxLegendScale\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\" alt=\"[^\"]+\"[^>]*>[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternTerrain = Pattern.compile(
            "<span id=\"ctl00_ContentBody_Localize6\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\" alt=\"[^\"]+\"[^>]*>[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternOwner = Pattern.compile(
            "<span class=\"minorCacheDetails\">[^\\w]*An?([^\\w]*Event)?[^\\w]*cache[^\\w]*by[^<]*<a href=\"[^\"]+\">([^<]+)</a>[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternOwnerReal = Pattern.compile(
            "<a id=\"ctl00_ContentBody_uxFindLinksHiddenByThisUser\" href=\"[^\"]*/seek/nearest\\.aspx\\?u=*([^\"]+)\">[^<]+</a>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternHidden = Pattern.compile(
            "<span[^>]*>[^\\w]*Hidden[^:]*:[^\\d]*((\\d+)\\/(\\d+)\\/(\\d+))[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternHiddenEvent = Pattern.compile(
            "<span[^>]*>[^\\w]*Event[^\\w]*Date[^:]*:[^\\w]*[a-zA-Z]+,[^\\d]*((\\d+)[^\\w]*(\\w+)[^\\d]*(\\d+))[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternFavourite = Pattern.compile(
            "<a id=\"uxFavContainerLink\"[^>]*>[^<]*<div[^<]*<span class=\"favorite-value\">[^\\d]*([0-9]+)[^\\d^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

    final Pattern patternFound = Pattern.compile(
            "<p>[^<]*<a id=\"ctl00_ContentBody_hlFoundItLog\"[^<]*<img src=\".*/images/stockholm/16x16/check\\.gif\"[^>]*>[^<]*</a>[^<]*</p>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternLatLon = Pattern.compile("<span id=\"uxLatLon\"[^>]*>([^<]*)<\\/span>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternLocation = Pattern.compile("<span id=\"ctl00_ContentBody_Location\"[^>]*>In ([^<]*)",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternHint = Pattern.compile(
            "<p>([^<]*<strong>)?[^\\w]*Additional Hints([^<]*<\\/strong>)?[^\\(]*\\(<a[^>]+>Encrypt</a>\\)[^<]*<\\/p>[^<]*<div id=\"div_hint\"[^>]*>(.*)</div>[^<]*<div id=[\\'|\"]dk[\\'|\"]",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternDescShort = Pattern.compile(
            "<div class=\"UserSuppliedContent\">[^<]*<span id=\"ctl00_ContentBody_ShortDescription\"[^>]*>((?:(?!</span>[^\\w^<]*</div>).)*)</span>[^\\w^<]*</div>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternDesc = Pattern.compile(
            "<div class=\"UserSuppliedContent\">[^<]*<span id=\"ctl00_ContentBody_LongDescription\"[^>]*>((?:(?!</span>[^\\w^<]*</div>).)*)</span>[^<]*</div>[^<]*<p>[^<]*</p>[^<]*<p>[^<]*<strong>[^\\w]*Additional Hints</strong>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternCountLogs = Pattern.compile(
            "<span id=\"ctl00_ContentBody_lblFindCounts\"><p>(.*)<\\/p><\\/span>", Pattern.CASE_INSENSITIVE);
    final Pattern patternCountLog = Pattern.compile(
            " src=\"\\/images\\/icons\\/([^\\.]*).gif\" alt=\"[^\"]*\" title=\"[^\"]*\" />([0-9]*)[^0-9]+",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    // final Pattern patternLogs = Pattern.compile("<table class=\"LogsTable[^\"]*\"[^>]*>((?:(?!</table>).)*)</table>[^<]*<p", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternLogs = Pattern.compile("<table class=\"LogsTable[^\"]*\"[^>]*>(.*)</table>[^<]*<p",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    /*
     * <tr>
     * <td class="Nothing">
     * <div class="FloatLeft LogDisplayLeft">
     * <p class="logOwnerProfileName">
     * <strong><a href="/profile/?guid=96c94662-f2c9-450a-99ef-4c034dcde72b" id="184034162">CERV.cz</a></strong>
     * </p>
     * <p class="logOwnerBadge"><img src='/images/icons/prem_user.gif' title='Premium Member' /> Premium Member</p>
     * <p class="logOwnerAvatar"><a href="/profile/?guid=96c94662-f2c9-450a-99ef-4c034dcde72b"><img src="/images/default_avatar.jpg" height='48' width='48' /></a></p>
     * <p class="logOwnerStats">
     * <img src="/images/icons/icon_smile.png" title="Caches Found" /> 567</div>
     * <div class="FloatLeft LogDisplayRight">
     * <div class="HalfLeft LogType">
     * <strong><img src="http://www.geocaching.com/images/icons/icon_smile.gif" alt="Found it" title="Found it" />&nbsp;Found it</strong>
     * </div>
     * <div class="HalfRight AlignRight">
     * <span class="minorDetails LogDate">09/03/2011</span>
     * </div>
     * <div class="Clear LogContent">
     * <p class="LogText">13:29 diky za kes!</p>
     * <div class="AlignRight">
     * <small><a href="log.aspx?LUID=8da01276-7881-4ec9-8d23-8938d7f2984e" title="View Log">View Log</a></small>
     * </div></div></div>
     * </td>
     * </tr>
     */
    final Pattern patternLogUser = Pattern.compile(
            "<p class=\"logOwnerProfileName\">[^<]*<strong>[^<]*<a[^>]*>([^<]+)</a>[^<]*</strong>[^<]*</p>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternLogFounds = Pattern.compile(
            "<p class=\"logOwnerStats\"><img[^>]*>[^\\d]*(\\d+)[^<]*</div>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternLogIcon = Pattern.compile(
            "<strong>[^<]*<img src=\"[^\"]*/images/icons/([^\"]+)\\.gif\"[^>]*>[^<]+</strong>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternLogDate = Pattern.compile(
            "<span class=\"minorDetails LogDate\">([0-9]+/[0-9]+/[0-9]+)[^<]*</span>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    final Pattern patternLogText = Pattern.compile("<p class=\"LogText\">((?:(?!</p>).)*)</p>",
            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

    final Pattern patternAttributes = Pattern.compile(
            "<h3 class=\"WidgetHeader\">[^<]*<img[^>]+>[^\\w]*Attributes[^<]*</h3>[^<]*<div class=\"WidgetBody\">(([^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+)[^<]*<p",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternAttributesInside = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+)\"[^>]*>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternSpoilers = Pattern.compile(
            "<span id=\"ctl00_ContentBody_Images\">((<a href=\"[^\"]+\"[^>]*>[^<]*<img[^>]+>[^<]*<span>[^>]+</span>[^<]*</a>[^<]*<br[^>]*>([^<]*(<br[^>]*>)+)?)+)[^<]*</span>",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternSpoilersInside = Pattern.compile(
            "[^<]*<a href=\"([^\"]+)\"[^>]*>[^<]*<img[^>]+>[^<]*<span>([^>]+)</span>[^<]*</a>[^<]*<br[^>]*>(([^<]*)(<br[^<]*>)+)?",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternInventory = Pattern.compile(
            "<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">[^\\w]*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?",
            Pattern.CASE_INSENSITIVE);
    final Pattern patternInventoryInside = Pattern.compile(
            "[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>",
            Pattern.CASE_INSENSITIVE);

    final CacheWrap caches = new CacheWrap();
    final Cache cache = new Cache();

    if (page.indexOf("Cache is Unpublished") > -1) {
        caches.error = "cache was unpublished";
        return caches;
    }

    if (page.indexOf("Sorry, the owner of this listing has made it viewable to Premium Members only.") != -1) {
        caches.error = "requested cache is for premium members only";
        return caches;
    }

    if (page.indexOf("has chosen to make this cache listing visible to Premium Members only.") != -1) {
        caches.error = "requested cache is for premium members only";
        return caches;
    }

    if (page.indexOf("<li>This cache is temporarily unavailable.") != -1) {
        cache.disabled = true;
    } else {
        cache.disabled = false;
    }

    if (page.indexOf("<li>This cache has been archived,") != -1) {
        cache.archived = true;
    } else {
        cache.archived = false;
    }

    if (page.indexOf("<p class=\"Warning\">This is a Premium Member Only cache.</p>") != -1) {
        cache.members = true;
    } else {
        cache.members = false;
    }

    cache.reason = reason;

    // cache geocode
    try {
        final Matcher matcherGeocode = patternGeocode.matcher(page);
        while (matcherGeocode.find()) {
            if (matcherGeocode.groupCount() > 0) {
                cache.geocode = (String) matcherGeocode.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse cache geocode
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache geocode");
    }

    // cache id
    try {
        final Matcher matcherCacheId = patternCacheId.matcher(page);
        while (matcherCacheId.find()) {
            if (matcherCacheId.groupCount() > 0) {
                cache.cacheid = (String) matcherCacheId.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse cache id
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache id");
    }

    // cache guid
    try {
        final Matcher matcherCacheGuid = patternCacheGuid.matcher(page);
        while (matcherCacheGuid.find()) {
            if (matcherCacheGuid.groupCount() > 0) {
                cache.guid = (String) matcherCacheGuid.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse cache guid
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache guid");
    }

    // name
    try {
        final Matcher matcherName = patternName.matcher(page);
        while (matcherName.find()) {
            if (matcherName.groupCount() > 0) {
                cache.name = Html.fromHtml(matcherName.group(1)).toString();
            }
        }
    } catch (Exception e) {
        // failed to parse cache name
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache name");
    }

    // owner real name
    try {
        final Matcher matcherOwnerReal = patternOwnerReal.matcher(page);
        while (matcherOwnerReal.find()) {
            if (matcherOwnerReal.groupCount() > 0) {
                cache.ownerReal = URLDecoder.decode(matcherOwnerReal.group(1));
            }
        }
    } catch (Exception e) {
        // failed to parse owner real name
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache owner real name");
    }

    final String username = settings.getUsername();
    if (cache.ownerReal != null && username != null && cache.ownerReal.equalsIgnoreCase(username)) {
        cache.own = true;
    }

    int pos = -1;
    String tableInside = page;

    pos = tableInside.indexOf("id=\"cacheDetails\"");
    if (pos == -1) {
        Log.e(Settings.tag, "cgeoBase.parseCache: ID \"cacheDetails\" not found on page");
        return null;
    }

    tableInside = tableInside.substring(pos);

    pos = tableInside.indexOf("<div class=\"CacheInformationTable\"");
    if (pos == -1) {
        Log.e(Settings.tag, "cgeoBase.parseCache: ID \"CacheInformationTable\" not found on page");
        return null;
    }

    tableInside = tableInside.substring(0, pos);

    if (tableInside != null && tableInside.length() > 0) {
        // cache terrain
        try {
            final Matcher matcherTerrain = patternTerrain.matcher(tableInside);
            while (matcherTerrain.find()) {
                if (matcherTerrain.groupCount() > 0) {
                    cache.terrain = new Float(
                            Pattern.compile("_").matcher(matcherTerrain.group(1)).replaceAll("."));
                }
            }
        } catch (Exception e) {
            // failed to parse terrain
            Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache terrain");
        }

        // cache difficulty
        try {
            final Matcher matcherDifficulty = patternDifficulty.matcher(tableInside);
            while (matcherDifficulty.find()) {
                if (matcherDifficulty.groupCount() > 0) {
                    cache.difficulty = new Float(
                            Pattern.compile("_").matcher(matcherDifficulty.group(1)).replaceAll("."));
                }
            }
        } catch (Exception e) {
            // failed to parse difficulty
            Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache difficulty");
        }

        // owner
        try {
            final Matcher matcherOwner = patternOwner.matcher(tableInside);
            while (matcherOwner.find()) {
                if (matcherOwner.groupCount() > 0) {
                    cache.owner = Html.fromHtml(matcherOwner.group(2)).toString();
                }
            }
        } catch (Exception e) {
            // failed to parse owner
            Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache owner");
        }

        // hidden
        try {
            final Matcher matcherHidden = patternHidden.matcher(tableInside);
            while (matcherHidden.find()) {
                if (matcherHidden.groupCount() > 0) {
                    cache.hidden = dateIn.parse(matcherHidden.group(1));
                }
            }
        } catch (Exception e) {
            // failed to parse cache hidden date
            Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache hidden date");
        }

        if (cache.hidden == null) {
            // event date
            try {
                final Matcher matcherHiddenEvent = patternHiddenEvent.matcher(tableInside);
                while (matcherHiddenEvent.find()) {
                    if (matcherHiddenEvent.groupCount() > 0) {
                        cache.hidden = dateEvIn.parse(matcherHiddenEvent.group(1));
                    }
                }
            } catch (Exception e) {
                // failed to parse cache event date
                Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache event date");
            }
        }

        // favourite
        try {
            final Matcher matcherFavourite = patternFavourite.matcher(tableInside);
            while (matcherFavourite.find()) {
                if (matcherFavourite.groupCount() > 0) {
                    cache.favouriteCnt = Integer.parseInt(matcherFavourite.group(1));
                }
            }
        } catch (Exception e) {
            // failed to parse favourite count
            Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse favourite count");
        }

        // cache size
        try {
            final Matcher matcherSize = patternSize.matcher(tableInside);
            while (matcherSize.find()) {
                if (matcherSize.groupCount() > 0) {
                    cache.size = matcherSize.group(1).toLowerCase();
                }
            }
        } catch (Exception e) {
            // failed to parse size
            Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache size");
        }
    }

    // cache found
    try {
        final Matcher matcherFound = patternFound.matcher(page);
        while (matcherFound.find()) {
            if (matcherFound.group() != null && matcherFound.group().length() > 0) {
                cache.found = true;
            }
        }
    } catch (Exception e) {
        // failed to parse found
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse found");
    }

    // cache type
    try {
        final Matcher matcherType = patternType.matcher(page);
        while (matcherType.find()) {
            if (matcherType.groupCount() > 0) {
                cache.type = cacheTypes.get(matcherType.group(1).toLowerCase());
            }
        }
    } catch (Exception e) {
        // failed to parse type
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache type");
    }

    // latitude and logitude
    try {
        final Matcher matcherLatLon = patternLatLon.matcher(page);
        while (matcherLatLon.find()) {
            if (matcherLatLon.groupCount() > 0) {
                cache.latlon = matcherLatLon.group(1);

                HashMap<String, Object> tmp = this.parseLatlon(cache.latlon);
                if (tmp.size() > 0) {
                    cache.latitude = (Double) tmp.get("latitude");
                    cache.longitude = (Double) tmp.get("longitude");
                    cache.latitudeString = (String) tmp.get("latitudeString");
                    cache.longitudeString = (String) tmp.get("longitudeString");
                    cache.reliableLatLon = true;
                }
                tmp = null;
            }
        }
    } catch (Exception e) {
        // failed to parse latitude and/or longitude
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache coordinates");
    }

    // cache location
    try {
        final Matcher matcherLocation = patternLocation.matcher(page);
        while (matcherLocation.find()) {
            if (matcherLocation.groupCount() > 0) {
                cache.location = matcherLocation.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse location
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache location");
    }

    // cache hint
    try {
        final Matcher matcherHint = patternHint.matcher(page);
        while (matcherHint.find()) {
            if (matcherHint.groupCount() > 2 && matcherHint.group(3) != null) {
                // replace linebreak and paragraph tags
                String hint = Pattern.compile("<(br|p)[^>]*>").matcher(matcherHint.group(3)).replaceAll("\n");
                if (hint != null) {
                    cache.hint = hint.replaceAll(Pattern.quote("</p>"), "").trim();
                }
            }
        }
    } catch (Exception e) {
        // failed to parse hint
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache hint");
    }

    // cache short description
    try {
        final Matcher matcherDescShort = patternDescShort.matcher(page);
        while (matcherDescShort.find()) {
            if (matcherDescShort.groupCount() > 0) {
                cache.shortdesc = matcherDescShort.group(1).trim();
            }
        }
    } catch (Exception e) {
        // failed to parse short description
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache short description");
    }

    // cache description
    try {
        final Matcher matcherDesc = patternDesc.matcher(page);
        while (matcherDesc.find()) {
            if (matcherDesc.groupCount() > 0) {
                cache.description = matcherDesc.group(1);
            }
        }
    } catch (Exception e) {
        // failed to parse short description
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache description");
    }

    // cache attributes
    try {
        final Matcher matcherAttributes = patternAttributes.matcher(page);
        while (matcherAttributes.find()) {
            if (matcherAttributes.groupCount() > 0) {
                final String attributesPre = matcherAttributes.group(1);
                final Matcher matcherAttributesInside = patternAttributesInside.matcher(attributesPre);

                while (matcherAttributesInside.find()) {
                    if (matcherAttributesInside.groupCount() > 1
                            && matcherAttributesInside.group(2).equalsIgnoreCase("blank") != true) {
                        if (cache.attributes == null) {
                            cache.attributes = new ArrayList<String>();
                        }
                        // by default, use the tooltip of the attribute
                        String attribute = matcherAttributesInside.group(2).toLowerCase();

                        // if the image name can be recognized, use the image name as attribute
                        String imageName = matcherAttributesInside.group(1).trim();
                        if (imageName.length() > 0) {
                            int start = imageName.lastIndexOf('/');
                            int end = imageName.lastIndexOf('.');
                            if (start >= 0 && end >= 0) {
                                attribute = imageName.substring(start + 1, end).replace('-', '_');
                            }
                        }
                        cache.attributes.add(attribute);
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache attributes
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache attributes");
    }

    // cache spoilers
    try {
        final Matcher matcherSpoilers = patternSpoilers.matcher(page);
        while (matcherSpoilers.find()) {
            if (matcherSpoilers.groupCount() > 0) {
                final String spoilersPre = matcherSpoilers.group(1);
                final Matcher matcherSpoilersInside = patternSpoilersInside.matcher(spoilersPre);

                while (matcherSpoilersInside.find()) {
                    if (matcherSpoilersInside.groupCount() > 0) {
                        final Spoiler spoiler = new Spoiler();
                        spoiler.url = matcherSpoilersInside.group(1);

                        if (matcherSpoilersInside.group(2) != null) {
                            spoiler.title = matcherSpoilersInside.group(2);
                        }
                        if (matcherSpoilersInside.group(4) != null) {
                            spoiler.description = matcherSpoilersInside.group(4);
                        }

                        if (cache.spoilers == null) {
                            cache.spoilers = new ArrayList<Spoiler>();
                        }
                        cache.spoilers.add(spoiler);
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache spoilers
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache spoilers");
    }

    // cache inventory
    try {
        cache.inventoryItems = 0;

        final Matcher matcherInventory = patternInventory.matcher(page);
        while (matcherInventory.find()) {
            if (cache.inventory == null) {
                cache.inventory = new ArrayList<Trackable>();
            }

            if (matcherInventory.groupCount() > 1) {
                final String inventoryPre = matcherInventory.group(2);

                if (inventoryPre != null && inventoryPre.length() > 0) {
                    final Matcher matcherInventoryInside = patternInventoryInside.matcher(inventoryPre);

                    while (matcherInventoryInside.find()) {
                        if (matcherInventoryInside.groupCount() > 0) {
                            final Trackable inventoryItem = new Trackable();
                            inventoryItem.guid = matcherInventoryInside.group(1);
                            inventoryItem.name = matcherInventoryInside.group(2);

                            cache.inventory.add(inventoryItem);
                            cache.inventoryItems++;
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache inventory
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache inventory (2)");
    }

    // cache logs counts
    try {
        final Matcher matcherLogCounts = patternCountLogs.matcher(page);
        while (matcherLogCounts.find()) {
            if (matcherLogCounts.groupCount() > 0) {
                final String[] logs = matcherLogCounts.group(1).split("<img");
                final int logsCnt = logs.length;

                for (int k = 1; k < logsCnt; k++) {
                    Integer type = null;
                    Integer count = null;
                    final Matcher matcherLog = patternCountLog.matcher(logs[k]);

                    if (matcherLog.find()) {
                        String typeStr = matcherLog.group(1);
                        String countStr = matcherLog.group(2);
                        if (typeStr != null && typeStr.length() > 0) {
                            if (logTypes.containsKey(typeStr.toLowerCase()) == true) {
                                type = logTypes.get(typeStr.toLowerCase());
                            }
                        }
                        if (countStr != null && countStr.length() > 0) {
                            count = Integer.parseInt(countStr);
                        }
                        if (type != null && count != null) {
                            cache.logCounts.put(type, count);
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        // failed to parse logs
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache log count");
    }

    // cache logs
    try {
        final Matcher matcherLogs = patternLogs.matcher(page);
        while (matcherLogs.find()) {
            Log.d(">>>>", "cnt: " + matcherLogs.groupCount());

            if (matcherLogs.groupCount() > 0) {
                final String[] logs = matcherLogs.group(1).split("</tr><tr>");
                final int logsCnt = logs.length;

                for (int k = 0; k < logsCnt; k++) {
                    final CacheLog logDone = new CacheLog();
                    Matcher matcher;

                    matcher = patternLogUser.matcher(logs[k]);
                    if (matcher.find() && matcher.groupCount() > 0) {
                        logDone.author = matcher.group(1).trim();
                        logDone.author = Html.fromHtml(logDone.author).toString();
                    }

                    matcher = patternLogFounds.matcher(logs[k]);
                    if (matcher.find() && matcher.groupCount() > 0) {
                        try {
                            logDone.found = Integer.parseInt(matcher.group(1).trim());
                        } catch (Exception e) {
                            // NaN
                        }
                    }

                    matcher = patternLogIcon.matcher(logs[k]);
                    if (matcher.find() && matcher.groupCount() > 0) {
                        if (logTypes.containsKey(matcher.group(1).toLowerCase()) == true) {
                            logDone.type = logTypes.get(matcher.group(1).toLowerCase());
                        } else {
                            logDone.type = logTypes.get("icon_note");
                        }
                    }

                    matcher = patternLogDate.matcher(logs[k]);
                    if (matcher.find() && matcher.groupCount() > 0) {
                        Date logDate = dateLogIn.parse(matcher.group(1));
                        if (logDate != null) {
                            logDone.date = logDate.getTime();
                        }
                    }

                    matcher = patternLogText.matcher(logs[k]);
                    if (matcher.find() && matcher.groupCount() > 0) {
                        logDone.log = matcher.group(1).trim();
                    }

                    if (cache.logs == null) {
                        cache.logs = new ArrayList<CacheLog>();
                    }
                    cache.logs.add(logDone);
                }
            }
        }
    } catch (Exception e) {
        // failed to parse logs
        Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache logs");
    }

    int wpBegin = 0;
    int wpEnd = 0;

    wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
    if (wpBegin != -1) { // parse waypoints
        final Pattern patternWpType = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg",
                Pattern.CASE_INSENSITIVE);
        final Pattern patternWpPrefixOrLookupOrLatlon = Pattern
                .compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>", Pattern.CASE_INSENSITIVE);
        final Pattern patternWpName = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>", Pattern.CASE_INSENSITIVE);
        final Pattern patternWpNote = Pattern.compile("colspan=\"6\">(.*)<\\/td>", Pattern.CASE_INSENSITIVE);

        String wpList = page.substring(wpBegin);

        wpEnd = wpList.indexOf("</p>");
        if (wpEnd > -1 && wpEnd <= wpList.length()) {
            wpList = wpList.substring(0, wpEnd);
        }

        if (wpList.indexOf("No additional waypoints to display.") == -1) {
            wpEnd = wpList.indexOf("</table>");
            wpList = wpList.substring(0, wpEnd);

            wpBegin = wpList.indexOf("<tbody>");
            wpEnd = wpList.indexOf("</tbody>");
            if (wpBegin >= 0 && wpEnd >= 0 && wpEnd <= wpList.length()) {
                wpList = wpList.substring(wpBegin + 7, wpEnd);
            }

            final String[] wpItems = wpList.split("<tr");

            String[] wp;
            for (int j = 1; j < wpItems.length; j++) {
                final Waypoint waypoint = new Waypoint();

                wp = wpItems[j].split("<td");

                // waypoint type
                try {
                    final Matcher matcherWpType = patternWpType.matcher(wp[3]);
                    while (matcherWpType.find()) {
                        if (matcherWpType.groupCount() > 0) {
                            waypoint.type = matcherWpType.group(1);
                            if (waypoint.type != null) {
                                waypoint.type = waypoint.type.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse type
                    Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint type");
                }

                // waypoint prefix
                try {
                    final Matcher matcherWpPrefix = patternWpPrefixOrLookupOrLatlon.matcher(wp[4]);
                    while (matcherWpPrefix.find()) {
                        if (matcherWpPrefix.groupCount() > 1) {
                            waypoint.prefix = matcherWpPrefix.group(2);
                            if (waypoint.prefix != null) {
                                waypoint.prefix = waypoint.prefix.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse prefix
                    Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint prefix");
                }

                // waypoint lookup
                try {
                    final Matcher matcherWpLookup = patternWpPrefixOrLookupOrLatlon.matcher(wp[5]);
                    while (matcherWpLookup.find()) {
                        if (matcherWpLookup.groupCount() > 1) {
                            waypoint.lookup = matcherWpLookup.group(2);
                            if (waypoint.lookup != null) {
                                waypoint.lookup = waypoint.lookup.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse lookup
                    Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint lookup");
                }

                // waypoint name
                try {
                    final Matcher matcherWpName = patternWpName.matcher(wp[6]);
                    while (matcherWpName.find()) {
                        if (matcherWpName.groupCount() > 0) {
                            waypoint.name = matcherWpName.group(1);
                            if (waypoint.name != null) {
                                waypoint.name = waypoint.name.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse name
                    Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint name");
                }

                // waypoint latitude and logitude
                try {
                    final Matcher matcherWpLatLon = patternWpPrefixOrLookupOrLatlon.matcher(wp[7]);
                    while (matcherWpLatLon.find()) {
                        if (matcherWpLatLon.groupCount() > 1) {
                            waypoint.latlon = Html.fromHtml(matcherWpLatLon.group(2)).toString();

                            final HashMap<String, Object> tmp = this.parseLatlon(waypoint.latlon);
                            if (tmp.size() > 0) {
                                waypoint.latitude = (Double) tmp.get("latitude");
                                waypoint.longitude = (Double) tmp.get("longitude");
                                waypoint.latitudeString = (String) tmp.get("latitudeString");
                                waypoint.longitudeString = (String) tmp.get("longitudeString");
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse latitude and/or longitude
                    Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint coordinates");
                }

                j++;
                if (wpItems.length > j) {
                    wp = wpItems[j].split("<td");
                }

                // waypoint note
                try {
                    final Matcher matcherWpNote = patternWpNote.matcher(wp[3]);
                    while (matcherWpNote.find()) {
                        if (matcherWpNote.groupCount() > 0) {
                            waypoint.note = matcherWpNote.group(1);
                            if (waypoint.note != null) {
                                waypoint.note = waypoint.note.trim();
                            }
                        }
                    }
                } catch (Exception e) {
                    // failed to parse note
                    Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint note");
                }

                if (cache.waypoints == null)
                    cache.waypoints = new ArrayList<Waypoint>();
                cache.waypoints.add(waypoint);
            }
        }
    }

    if (cache.latitude != null && cache.longitude != null) {
        cache.elevation = getElevation(cache.latitude, cache.longitude);
    }

    cache.updated = System.currentTimeMillis();
    cache.detailedUpdate = System.currentTimeMillis();
    cache.detailed = true;
    caches.cacheList.add(cache);

    return caches;
}