edu.cens.loci.ui.PlaceViewActivity.java Source code

Java tutorial

Introduction

Here is the source code for edu.cens.loci.ui.PlaceViewActivity.java

Source

/*******************************************************************************
 * Copyright 2012 The Regents of the University of California
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package edu.cens.loci.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.json.JSONException;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Entity;
import android.content.EntityIterator;
import android.content.Intent;
import android.content.Entity.NamedContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

import edu.cens.loci.Constants;
import edu.cens.loci.LociConfig;
import edu.cens.loci.R;
import edu.cens.loci.Constants.Intents;
import edu.cens.loci.Constants.PlacesList;
import edu.cens.loci.Constants.Intents.UI;
import edu.cens.loci.classes.LociCircleArea;
import edu.cens.loci.classes.LociLocation;
import edu.cens.loci.classes.LociPlace;
import edu.cens.loci.classes.LociVisit;
import edu.cens.loci.classes.LociWifiFingerprint;
import edu.cens.loci.classes.PlacesSource;
import edu.cens.loci.classes.Sources;
import edu.cens.loci.classes.LociWifiFingerprint.APInfoMapItem;
import edu.cens.loci.classes.PlacesSource.DataKind;
import edu.cens.loci.provider.LociDbUtils;
import edu.cens.loci.provider.LociProvider;
import edu.cens.loci.provider.LociContract.Data;
import edu.cens.loci.provider.LociContract.Places;
import edu.cens.loci.provider.LociContract.PlacesEntity;
import edu.cens.loci.provider.LociContract.Visits;
import edu.cens.loci.provider.LociContract.CommonPlaceDataKinds.GpsCircleArea;
import edu.cens.loci.provider.LociContract.CommonPlaceDataKinds.Keyword;
import edu.cens.loci.provider.LociContract.CommonPlaceDataKinds.Note;
import edu.cens.loci.provider.LociContract.CommonPlaceDataKinds.StructuredPostal;
import edu.cens.loci.provider.LociContract.CommonPlaceDataKinds.Website;
import edu.cens.loci.provider.LociContract.CommonPlaceDataKinds.WifiFingerprint;
import edu.cens.loci.ui.maps.overlays.DotOverlay;
import edu.cens.loci.utils.LocationUtils;
import edu.cens.loci.utils.MyDateUtils;
import edu.cens.loci.utils.MyLog;
import edu.cens.loci.utils.NotifyingAsyncQueryHandler;

public class PlaceViewActivity extends MapActivity
        implements AdapterView.OnItemClickListener, NotifyingAsyncQueryHandler.AsyncQueryListener {

    private static final String TAG = "PlaceViewActivity";

    private static final int LIST_ACTION_NO_ACTION = 1;
    private static final int LIST_ACTION_VIEW_VISITS = 2;
    private static final int LIST_ACTION_VIEW_WIFIS = 3;
    private static final int LIST_ACTION_ADD = 4;
    private static final int LIST_ACTION_DELETE = 5;
    private static final int LIST_ACTION_POSTAL = 6;
    //private static final int LIST_ACTION_KEYWORD = 7;
    private static final int LIST_ACTION_WEBSITE = 8;

    private Uri mUri;

    private TextView mNameView;
    private MapView mMapView;
    private ListView mListView;

    private long mPlaceId;
    private LociPlace mPlace;
    private LociDbUtils mDbUtils;

    ArrayList<ViewEntry> mWifiEntries = new ArrayList<ViewEntry>();
    ArrayList<ViewEntry> mGpsEntries = new ArrayList<ViewEntry>();
    ArrayList<ViewEntry> mPostalEntries = new ArrayList<ViewEntry>();
    ArrayList<ViewEntry> mTagEntries = new ArrayList<ViewEntry>();
    ArrayList<ViewEntry> mWebsiteEntries = new ArrayList<ViewEntry>();
    ArrayList<ViewEntry> mOtherEntries = new ArrayList<ViewEntry>();

    ArrayList<ArrayList<ViewEntry>> mSections = new ArrayList<ArrayList<ViewEntry>>();

    protected Uri mLookupUri;
    private NotifyingAsyncQueryHandler mHandler;

    protected LayoutInflater mInflater;

    private static final int TOKEN_ENTITIES = 1;

    private boolean mHasEntities = false;

    private ArrayList<Entity> mEntities = new ArrayList<Entity>();

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // parse incoming data
        final Intent intent = getIntent();
        final String action = intent.getAction();
        if (Intent.ACTION_VIEW.equals(action)) {
            mUri = intent.getData();
            if (mUri == null) {
                MyLog.e(LociConfig.D.ERROR, TAG, "intent.getData() is empty, exiting.");
                finish();
            }
            MyLog.d(LociConfig.D.UI.DEBUG, TAG, "mUri=" + mUri.toString());
        } else {
            MyLog.e(LociConfig.D.ERROR, TAG, "Unknown action, exiting.");
            finish();
            return;
        }
        mPlaceId = LociProvider.checkPlaceIdUri(mUri);

        if (mPlaceId < 0) {
            MyLog.e(LociConfig.D.ERROR, TAG, "Invalid uri, exiting.");
            finish();
        }

        mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.place_view);

        mNameView = (TextView) findViewById(R.id.name);
        mMapView = (MapView) findViewById(R.id.map);

        mListView = (ListView) findViewById(R.id.place_data);
        mListView.setOnItemClickListener(this);
        mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
        mListView.setEmptyView(findViewById(android.R.id.empty));

        mDbUtils = new LociDbUtils(this);

        mPlace = mDbUtils.getPlace(mPlaceId);

        //DEBUG
        MyLog.d(LociConfig.D.UI.DEBUG, TAG, "viewing..." + mPlace.toString());

        mHandler = new NotifyingAsyncQueryHandler(this, this);

        // The order they're added to mSections dictates the order they are diplayed in the list.
        mSections.add(mGpsEntries);
        mSections.add(mWifiEntries);
        mSections.add(mPostalEntries);
        mSections.add(mTagEntries);
        mSections.add(mWebsiteEntries);
        mSections.add(mOtherEntries);
    }

    public void onResume() {

        mPlace = mDbUtils.getPlace(mPlaceId);

        super.onResume();
        updateList();
    }

    private synchronized void startEntityQuery() {

        final long placeId = LociProvider.checkPlaceIdUri(mUri);

        mHandler.startQuery(TOKEN_ENTITIES, null, PlacesEntity.CONTENT_URI, null, Places._ID + "=?",
                new String[] { String.valueOf(placeId), }, null);
    }

    private void updateList() {

        if (mPlace == null) {
            MyLog.e(LociConfig.D.ERROR, TAG, "No Place Info");
            if (mPlaceId > 0) {
                MyLog.e(LociConfig.D.ERROR, TAG, "Reload place..." + mPlaceId);
                mPlace = mDbUtils.getPlace(mPlaceId);
            }
            if (mPlace == null)
                finish();
        }

        if (mPlace.state == Places.STATE_SUGGESTED)
            updateListForSuggestedPlace();
        else
            updateListDefault();
    }

    private void updatePlaceName() {
        String name = mPlace.name;
        mNameView.setText(name);
    }

    private void updateMapView(LociCircleArea circle) {

        mMapView.setClickable(true);
        mMapView.setSatellite(false);
        mMapView.getOverlays().clear();

        if (circle != null) {

            // check if the coordinate is valid?
            if (LocationUtils.isValidGeoPoint(circle.getGeoPoint())) {
                // draw overlay
                MapController mc = mMapView.getController();
                mc.setZoom(16);
                mc.setCenter(circle.getGeoPoint());
                DotOverlay dotOverlay = new DotOverlay(circle.getLocation());
                dotOverlay.setTapAction(this, getMapEditViewIntent(circle, false));
                mMapView.getOverlays().clear();
                mMapView.getOverlays().add(dotOverlay);
            }
        }
    }

    private Intent getMapEditViewIntent(LociCircleArea circle, boolean movable) {
        Intent intent = new Intent(this, MapEditViewActivity.class);
        intent.putExtra(Constants.Intents.UI.MAP_EDIT_CIRCLE_EXTRA_KEY, circle);
        intent.putExtra(Constants.Intents.UI.MAP_EDIT_MODE_EXTRA_KEY, movable);
        return intent;
    }

    private void updateListDefault() {
        updatePlaceName();

        if (mPlace.areas != null)
            updateMapView(mPlace.areas.get(0));

        startEntityQuery();
    }

    private void updateListForSuggestedPlace() {

        updatePlaceName();
        updateMapView(mDbUtils.getPlacePositionEstimate(mPlace.placeId));

        ArrayList<ViewEntry> items = new ArrayList<ViewEntry>();

        // recent visit time
        String recentVisitTime = getRecentVisitSubstring(); //"May 4, 3:00pm, 1hr";
        items.add(new ViewEntry(LIST_ACTION_VIEW_VISITS, R.drawable.ic_clock_strip_desk_clock, "View recent visits",
                recentVisitTime, null));

        String apsAbstract = "Not available";
        // wifis
        if (mPlace.wifis.size() > 0)
            //apsAbstract = getWifiInfoSubstring(5, mPlace.wifis.get(0).toJsonString());
            apsAbstract = mPlace.wifis.get(0).getWifiInfoSubstring(5);

        //String apsAbstract = getWifiInfoSubstring(5); //"CENSTemp, UCLAWAN, Go away this Wifi is mine and not yours";
        ViewEntry entry = new ViewEntry(LIST_ACTION_VIEW_WIFIS, R.drawable.ic_settings_wireless, "View Wi-Fi APs",
                apsAbstract, null);
        try {
            if (mPlace.wifis != null && mPlace.wifis.size() > 0)
                entry.extra_string = mPlace.wifis.get(0).toJsonObject().toString();
            else
                entry.extra_string = "";
        } catch (JSONException e) {
            MyLog.e(LociConfig.D.JSON, TAG, "updateListForSuggestedPlace: json failed.");
            entry.extra_string = "";
        }

        items.add(entry);

        // Add
        //Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT, ContentUris.withAppendedId(Places.CONTENT_URI, mPlace.placeId));
        Intent intent = new Intent(Intents.UI.ACTION_CREATE_OR_ADDTO_FROM_SUGGESTED_PLACE,
                ContentUris.withAppendedId(Places.CONTENT_URI, mPlace.placeId));
        intent.putExtra(UI.TITLE_EXTRA_KEY, "Places");
        //intent.setType(Places.CONTENT_TYPE);
        intent.putExtra(UI.FILTER_STATE_EXTRA_KEY, Constants.Intents.UI.FILTER_STATE_REGISTERED);
        intent.putExtra(UI.FILTER_TYPE_EXTRA_KEY,
                Constants.Intents.UI.FILTER_TYPE_GPS | Constants.Intents.UI.FILTER_TYPE_WIFI);
        if (mPlace.wifis == null || mPlace.wifis.size() == 0) {
            intent.putExtra(UI.LIST_ORDER_EXTRA_KEY, PlacesList.LIST_ORDER_TYPE_NAME);
        } else {
            intent.putExtra(UI.LIST_ORDER_EXTRA_KEY, PlacesList.LIST_ORDER_TYPE_WIFI_SIMILARITY);
            intent.putExtra(UI.LIST_ORDER_EXTRA_WIFI_KEY, mPlace.wifis.get(0).toJsonString());
        }
        items.add(new ViewEntry(LIST_ACTION_ADD, R.drawable.sym_action_add, "Add place", null, intent));

        // delete
        items.add(new ViewEntry(LIST_ACTION_DELETE, R.drawable.ic_menu_delete, "Delete suggestion", null,
                new Intent()));

        ViewEntryAdapter adapter = new ViewEntryAdapter(this, R.layout.place_view_list_item, items);
        mListView.setAdapter(adapter);
    }

    private String getRecentVisitSubstring() {
        // get recent visit time
        ArrayList<LociVisit> visits = mDbUtils.getBaseVisits(mPlace.placeId, Visits.ENTER + " DESC",
                String.valueOf(1));

        String recentVisitTime = "Not available";

        if (visits.size() > 0) {
            long enter = visits.get(0).enter;
            long exit = visits.get(0).exit;

            // Pull out string in format [relative], [date]
            //CharSequence dateClause = DateUtils.formatDateRange(this, enter, enter,
            //        DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
            //        DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_YEAR);
            //recentVisitTime = dateClause + ", ";

            recentVisitTime = MyDateUtils.getAbrv_h_m_MMM_d(visits.get(0).enter) + ", ";
            recentVisitTime += "stayed ";
            recentVisitTime += MyDateUtils.humanReadableDuration(exit - enter, 2);
        }

        return recentVisitTime;
    }

    private CharSequence[] getAllVisits() {
        ArrayList<LociVisit> visits = mDbUtils.getBaseVisits(mPlace.placeId, Visits.ENTER + " DESC", "5");
        CharSequence[] visitLabels = new CharSequence[visits.size()];
        int count = 0;
        for (LociVisit visit : visits) {
            visitLabels[count++] = MyDateUtils.getAbrv_h_m_MMM_d(visit.enter) + ", stayed "
                    + MyDateUtils.humanReadableDuration(visit.exit - visit.enter, 2);
        }

        MyLog.i(LociConfig.D.UI.LIST, TAG, "getAllVisits: count=" + count + " visits.size=" + visits.size());

        return visitLabels;
    }

    public void onQueryComplete(int token, Object cookie, final Cursor cursor) {
        final ArrayList<Entity> oldEntities = mEntities;
        (new AsyncTask<Void, Void, ArrayList<Entity>>() {
            @Override
            protected ArrayList<Entity> doInBackground(Void... params) {
                ArrayList<Entity> newEntities = new ArrayList<Entity>(cursor.getCount());
                EntityIterator iterator = Places.newEntityIterator(cursor);
                try {
                    while (iterator.hasNext()) {
                        Entity entity = iterator.next();
                        newEntities.add(entity);
                    }
                } finally {
                    iterator.close();
                }
                return newEntities;
            }

            @Override
            protected void onPostExecute(ArrayList<Entity> newEntities) {
                if (newEntities == null) {
                    // There was an error loading.
                    return;
                }
                synchronized (PlaceViewActivity.this) {
                    if (mEntities != oldEntities) {
                        // Multiple async tasks were in flight and we
                        // lost the race.
                        return;
                    }
                    mEntities = newEntities;
                    mHasEntities = true;
                }
                considerBindData();
            }
        }).execute();
    }

    private void considerBindData() {
        if (mHasEntities) {
            bindData();
        }
    }

    private void bindData() {

        // Build up the contact entries
        buildEntries();

    }

    static String buildActionString(DataKind kind, ContentValues values, boolean lowerCase, Context context) {
        if (kind.actionHeader == null) {
            return null;
        }
        CharSequence actionHeader = kind.actionHeader.inflateUsing(context, values);
        if (actionHeader == null) {
            return null;
        }
        return lowerCase ? actionHeader.toString().toLowerCase() : actionHeader.toString();
    }

    static String buildDataString(DataKind kind, ContentValues values, Context context) {
        if (kind.actionBody == null) {
            return null;
        }
        CharSequence actionBody = kind.actionBody.inflateUsing(context, values);
        return actionBody == null ? null : actionBody.toString();
    }

    public static final class ViewEntry {
        public String label = null;
        public String data = null;
        public Uri uri = null;

        public int action = -1;
        public int icon = -1;
        public String text = null;
        public String subtext = null;
        public Intent intent = null;
        public String extra_string = null;
        public double extra_double1 = -1;
        public double extra_double2 = -1;
        public float extra_float1 = -1;

        private ViewEntry() {
        }

        public ViewEntry(int action, int icon, String text, String subtext, Intent intent) {
            this.action = action;
            this.icon = icon;
            this.text = text;
            this.subtext = subtext;
            this.intent = intent;
        }

        public static ViewEntry fromValues(Context context, String mimeType, DataKind kind, long placeId,
                long dataId, ContentValues values) {
            final ViewEntry item = new ViewEntry();
            item.label = buildActionString(kind, values, false, context);
            item.data = buildDataString(kind, values, context);
            item.uri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId);
            if (kind.iconRes > 0) {
                item.icon = kind.iconRes;
            }
            return item;
        }
    }

    public static final class ViewEntryAdapter extends BaseAdapter {

        private final List<ViewEntry> mList;
        private final LayoutInflater mInflater;
        private int mLayout;

        public ViewEntryAdapter(Context context, int layout, ArrayList<ViewEntry> list) {
            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mLayout = layout;
            mList = list;
        }

        public int getCount() {
            return mList.size();
        }

        public Object getItem(int position) {
            return mList.get(position);
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {

            if (convertView == null)
                convertView = mInflater.inflate(mLayout, parent, false);

            ViewEntry item = mList.get(position);
            convertView.setTag(item);

            ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
            TextView line1 = (TextView) convertView.findViewById(android.R.id.text1);
            View line2 = convertView.findViewById(R.id.subtext);

            if (item.icon > 0)
                icon.setImageResource(item.icon);

            line1.setText(item.text);

            if (TextUtils.isEmpty(item.subtext)) {
                line2.setVisibility(View.GONE);
            } else {
                line2.setVisibility(View.VISIBLE);
                TextView subtext = (TextView) convertView.findViewById(R.id.subtext);
                subtext.setText(item.subtext);
            }

            return convertView;
        }

    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

        if (view.getTag() instanceof ViewEntry) {
            ViewEntry item = (ViewEntry) view.getTag();
            switch (item.action) {
            case LIST_ACTION_VIEW_VISITS:
                showDialog(DIALOG_VISITS);
                break;
            case LIST_ACTION_VIEW_WIFIS:
                Bundle args = new Bundle();
                args.putString("wifi", item.extra_string);
                showDialog(DIALOG_WIFI, args);
                break;
            case LIST_ACTION_ADD:
                startActivityForResult(item.intent, SUBACTIVITY_ADD_PLACE);
                break;
            case LIST_ACTION_DELETE:
                showDialog(DIALOG_CONFIRM_DELETE, null);
                break;
            case LIST_ACTION_WEBSITE:
            case LIST_ACTION_POSTAL:
                if (item.intent != null)
                    startActivity(item.intent);
                break;
            }
        }
    }

    private static final int SUBACTIVITY_ADD_PLACE = 1;
    private static final int SUBACTIVITY_VIEW_PLACE = 2;

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        Log.d(TAG, "onActivityResult:" + String.format(" requestCode=%d resultCode=%d ", requestCode, resultCode));

        switch (requestCode) {
        case SUBACTIVITY_ADD_PLACE:
            if (resultCode == RESULT_OK) {

                long placeId = ContentUris.parseId(data.getData());

                if (mPlace.state == Places.STATE_SUGGESTED) {
                    if (placeId != mPlaceId) {
                        // A suggested place has been merged to an existing place
                        // update all visit's placeId's here
                        LociDbUtils dbUtils = new LociDbUtils(this);
                        dbUtils.updateVisitPlaceId(mPlaceId, placeId);
                        mPlaceId = placeId;
                    }
                }

                setResult(RESULT_OK, data);
            }
            break;
        case SUBACTIVITY_VIEW_PLACE:
            if (resultCode == RESULT_OK) {

            }
        }
    }

    @Override
    protected boolean isRouteDisplayed() {
        // TODO Auto-generated method stub
        return false;
    }

    /**
     * Build up the entries to display on the screen.
     *
     * @param personCursor the URI for the contact being displayed
     */
    private final void buildEntries() {

        final Context context = this;
        final Sources sources = Sources.getInstance(context);

        ArrayList<ViewEntry> items = new ArrayList<ViewEntry>();

        int typeIcon = R.drawable.icon_question;
        String typeString = "Unknown";

        if (mPlace.type == Places.TYPE_GPS) {
            typeIcon = R.drawable.icon_satellite;
            typeString = "GPS";
        } else if (mPlace.type == Places.TYPE_WIFI) {
            typeIcon = R.drawable.icon_wifi;
            typeString = "Wi-Fi";
        }

        // detection type
        items.add(new ViewEntry(LIST_ACTION_NO_ACTION, typeIcon, "Dectection Sensor", typeString, null));

        // recent visit time
        String recentVisitTime = getRecentVisitSubstring(); //"May 4, 3:00pm, 1hr";
        items.add(new ViewEntry(LIST_ACTION_VIEW_VISITS, R.drawable.ic_clock_strip_desk_clock, "View recent visits",
                recentVisitTime, null));

        for (Entity entity : mEntities) {
            final ContentValues entValues = entity.getEntityValues();
            final String accountType = entValues.getAsString(Places.ACCOUNT_TYPE);
            final long placeId = entValues.getAsLong(Places._ID);

            for (NamedContentValues subValue : entity.getSubValues()) {
                final ContentValues entryValues = subValue.values;
                entryValues.put(Places.Data.PLACE_ID, placeId);
                final long dataId = entryValues.getAsLong(Data._ID);
                final String mimeType = entryValues.getAsString(Data.MIMETYPE);
                if (mimeType == null)
                    continue;

                final DataKind kind = sources.getKindOrFallback(accountType, mimeType, this,
                        PlacesSource.LEVEL_MIMETYPES);
                if (kind == null)
                    continue;

                //Log.e(TAG, "buildEntries: dataId=" + dataId + ", mimeType=" + mimeType);

                // public ViewEntry(int action, int icon, String text, String subtext, Intent intent) {

                if (WifiFingerprint.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    String fingerprint = entryValues.getAsString(WifiFingerprint.FINGERPRINT);
                    long timestamp = entryValues.getAsLong(WifiFingerprint.TIMESTAMP);
                    String subtext = "Captured at " + MyDateUtils.getAbrv_MMM_d_h_m(timestamp);
                    //Log.d(TAG, fingerprint);
                    //String apsAbstract = getWifiInfoSubstring(5, fingerprint); 
                    ViewEntry item = new ViewEntry(LIST_ACTION_VIEW_WIFIS, R.drawable.ic_settings_wireless,
                            "View Wi-Fi APs", subtext, null);
                    item.extra_string = fingerprint;
                    mWifiEntries.add(item);
                } else if (GpsCircleArea.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    double lat = entryValues.getAsDouble(GpsCircleArea.LATITUDE);
                    double lon = entryValues.getAsDouble(GpsCircleArea.LONGITUDE);
                    float rad = entryValues.getAsFloat(GpsCircleArea.RADIUS);
                    //Log.d(TAG, "lat=" + lat + ",lon=" + lon + ",rad=" + rad);
                    ViewEntry item = new ViewEntry(-1, -1, null, null, null);
                    item.extra_double1 = lat;
                    item.extra_double2 = lon;
                    item.extra_float1 = rad;
                    mGpsEntries.add(item);
                } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    ViewEntry item = ViewEntry.fromValues(context, mimeType, kind, placeId, dataId, entryValues);
                    String uri = "geo:0,0?q=" + TextUtils.htmlEncode(item.data);
                    item.intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
                    item.action = LIST_ACTION_POSTAL;
                    item.text = item.label;
                    item.subtext = item.data;
                    mPostalEntries.add(item);
                } else if (Keyword.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    ViewEntry item = ViewEntry.fromValues(context, mimeType, kind, placeId, dataId, entryValues);
                    item.text = item.data;
                    item.subtext = null;
                    mTagEntries.add(item);
                } else if (Note.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    ViewEntry item = ViewEntry.fromValues(context, mimeType, kind, placeId, dataId, entryValues);
                    item.text = item.label;
                    item.subtext = item.data;
                    mOtherEntries.add(item);
                } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    ViewEntry item = ViewEntry.fromValues(context, mimeType, kind, placeId, dataId, entryValues);
                    item.uri = null;
                    item.action = LIST_ACTION_WEBSITE;
                    item.text = item.label;
                    item.subtext = item.data;
                    item.intent = new Intent(Intent.ACTION_VIEW, Uri.parse(item.data));
                    mWebsiteEntries.add(item);
                }
            }
        }

        for (ViewEntry item : mWifiEntries) {
            items.add(item);
        }
        mWifiEntries.clear();
        for (ViewEntry item : mPostalEntries) {
            items.add(item);
        }
        mPostalEntries.clear();
        for (ViewEntry item : mTagEntries) {
            items.add(item);
        }
        mTagEntries.clear();
        for (ViewEntry item : mWebsiteEntries) {
            items.add(item);
        }
        mWebsiteEntries.clear();
        for (ViewEntry item : mOtherEntries) {
            items.add(item);
        }
        mOtherEntries.clear();
        // Log.d(TAG, "size of items = " + items.size());

        ViewEntryAdapter adapter = new ViewEntryAdapter(this, R.layout.place_view_list_item, items);
        mListView.setAdapter(adapter);
    }

    private static final int DIALOG_WIFI = 1;
    private static final int DIALOG_VISITS = 2;
    private static final int DIALOG_CONFIRM_DELETE = 3;
    private static final int DIALOG_CONFIRM_BLOCK = 4;
    private static final int DIALOG_CONFIRM_UNBLOCK = 5;

    @Override
    protected Dialog onCreateDialog(int id, Bundle args) {
        LayoutInflater factory = LayoutInflater.from(this);

        switch (id) {
        case DIALOG_WIFI:
            final View wifiView = factory.inflate(R.layout.dialog_wifi_view, null);
            final TableLayout wifiTable = (TableLayout) wifiView.findViewById(R.id.wifi_table);
            //updateWifiList(wifiTable, mPlace.wifis.get(0));
            String wifiJson = args.getString("wifi");
            //Log.d(TAG, "createDialog: " + wifiJson);
            try {
                updateWifiList(wifiTable, new LociWifiFingerprint(wifiJson));
            } catch (JSONException e) {
                MyLog.e(LociConfig.D.JSON, TAG, "updateWifiList: json failed.");
                e.printStackTrace();
                return null;
            }
            return new AlertDialog.Builder(this).setIcon(R.drawable.ic_settings_wireless)
                    .setTitle("Nearby Wi-Fi Access Points").setView(wifiView)
                    .setPositiveButton("Close", new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int which) {
                            // TODO Auto-generated method stub

                        }
                    }).create();
        case DIALOG_VISITS:
            return new AlertDialog.Builder(this).setIcon(R.drawable.ic_clock_strip_desk_clock)
                    .setTitle("Recent visits").setItems(getAllVisits(), new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    }).setPositiveButton("Close", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    }).create();
        case DIALOG_CONFIRM_DELETE:
            return new AlertDialog.Builder(this).setIcon(R.drawable.ic_menu_delete).setTitle("Are you sure?")
                    .setPositiveButton("Delete", new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int which) {
                            //mDbUtils.updatePlaceState(mPlaceId, Places.STATE_DELETED);

                            MyLog.d(LociConfig.D.UI.DEBUG, TAG, "[delete] before");
                            mDbUtils.checkPlaceTable();
                            mDbUtils.checkDataTable();
                            mDbUtils.deletePlace(mPlaceId);
                            MyLog.d(LociConfig.D.UI.DEBUG, TAG, "[delete] after");
                            mDbUtils.checkPlaceTable();
                            mDbUtils.checkDataTable();
                            finish();
                        }
                    }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    }).create();
        case DIALOG_CONFIRM_BLOCK:
            return new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_menu_close_clear_cancel)
                    .setTitle("Are you sure?").setMessage("Visits to a blocked place will not be recognized.")
                    .setPositiveButton("Block", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            mDbUtils.updatePlaceState(mPlaceId, Places.STATE_BLOCKED);
                            finish();
                        }
                    }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    }).create();
        case DIALOG_CONFIRM_UNBLOCK:
            return new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_menu_close_clear_cancel)
                    .setTitle("Are you sure?").setPositiveButton("Unblock", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            mDbUtils.updatePlaceState(mPlaceId, Places.STATE_REGISTERED);
                            finish();
                        }
                    }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    }).create();
        }
        return null;
    }

    private ArrayList<View> mAddedRows = new ArrayList<View>();

    private void updateWifiList(TableLayout table, LociWifiFingerprint wifi) {

        ArrayList<WifiViewListItem> items = new ArrayList<WifiViewListItem>();

        HashMap<String, APInfoMapItem> apMap = wifi.getAps();
        Set<String> keys = apMap.keySet();
        Iterator<String> iter = keys.iterator();
        while (iter.hasNext()) {
            String bssid = iter.next();
            APInfoMapItem ap = apMap.get(bssid);
            items.add(new WifiViewListItem(bssid, ap.ssid, ap.rss, ap.count, ap.rssBuckets));
        }

        Collections.sort(items);

        table.setColumnCollapsed(0, false);
        table.setColumnCollapsed(1, true);
        table.setColumnShrinkable(0, true);

        for (int i = 0; i < mAddedRows.size(); i++) {
            table.removeView(mAddedRows.get(i));
        }
        mAddedRows.clear();

        int totalCount = wifi.getScanCount();

        for (WifiViewListItem item : items) {
            TableRow row = new TableRow(this);

            TextView ssidView = new TextView(this);
            ssidView.setText(item.ssid);
            //ssidView.setText("very very very veryvery very very very very very");
            ssidView.setPadding(2, 2, 2, 2);
            ssidView.setTextColor(0xffffffff);

            TextView bssidView = new TextView(this);
            bssidView.setText(item.bssid);
            bssidView.setPadding(2, 2, 2, 2);
            bssidView.setTextColor(0xffffffff);

            TextView cntView = new TextView(this);
            cntView.setText("" + (item.count * 100) / totalCount);
            cntView.setPadding(2, 2, 2, 2);
            cntView.setGravity(Gravity.CENTER);
            cntView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);

            TextView rssView = new TextView(this);
            rssView.setText("" + item.rss);
            rssView.setPadding(2, 2, 6, 2);
            rssView.setGravity(Gravity.CENTER);
            rssView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);

            row.addView(ssidView, new TableRow.LayoutParams(0));
            row.addView(bssidView, new TableRow.LayoutParams(1));
            row.addView(cntView, new TableRow.LayoutParams(2));
            row.addView(rssView, new TableRow.LayoutParams(3));

            //Log.d(TAG, item.ssid);
            for (int i = 0; i < item.rssBuckets.length; i++) {
                TextView box = new TextView(this);
                box.setText("  ");
                box.setGravity(Gravity.RIGHT);
                box.setPadding(2, 2, 2, 2);
                box.setHeight(15);
                box.setGravity(Gravity.CENTER_VERTICAL);

                float colorVal = 256 * ((float) item.rssBuckets[i] / (float) wifi.getScanCount());
                //Log.d(TAG, "colorVal=" + (int) colorVal + ", " + item.histogram[i]);
                int colorValInt = ((int) colorVal) - 1;
                if (colorValInt < 0)
                    colorValInt = 0;

                box.setBackgroundColor(0xff000000 + colorValInt);//+ 0x000000ff * (item.histogram[i]/totScan));
                box.setTextColor(0xffffffff);

                row.addView(box, new TableRow.LayoutParams(4 + i));
            }

            row.setGravity(Gravity.CENTER);

            table.addView(row, new TableLayout.LayoutParams());
            table.setColumnStretchable(3, true);
            mAddedRows.add(row);
        }

    }

    public static final class WifiViewListItem implements Comparable<WifiViewListItem> {
        public String bssid = null;
        public String ssid = null;
        public int rss = 0;
        public int count = 0;
        public int[] rssBuckets = null;

        public WifiViewListItem(String bssid, String ssid, int rss, int count, int[] buckets) {
            this.bssid = bssid;
            this.ssid = ssid;
            this.rss = rss;
            this.count = count;
            this.rssBuckets = buckets;
        }

        public int compareTo(WifiViewListItem item) {
            return item.count - this.count;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        final MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.view, menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        if (mPlace.state == Places.STATE_SUGGESTED) {
            menu.findItem(R.id.menu_delete).setVisible(false);
            menu.findItem(R.id.menu_edit).setVisible(false);
            menu.findItem(R.id.menu_block).setVisible(false);
            menu.findItem(R.id.menu_unblock).setVisible(false);
        } else if (mPlace.state == Places.STATE_BLOCKED) {
            menu.findItem(R.id.menu_block).setVisible(false);
            menu.findItem(R.id.menu_unblock).setVisible(true);
        } else if (mPlace.state == Places.STATE_REGISTERED) {
            menu.findItem(R.id.menu_block).setVisible(true);
            menu.findItem(R.id.menu_unblock).setVisible(false);
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
        case R.id.menu_edit:
            Intent intent = new Intent(Intent.ACTION_EDIT,
                    ContentUris.withAppendedId(Places.CONTENT_URI, mPlace.placeId));
            startActivity(intent);
            return true;
        case R.id.menu_delete:
            showDialog(DIALOG_CONFIRM_DELETE, null);
            return true;
        case R.id.menu_block:
            showDialog(DIALOG_CONFIRM_BLOCK, null);
            return true;
        case R.id.menu_unblock:
            showDialog(DIALOG_CONFIRM_UNBLOCK, null);
            return true;
        }
        return false;
    }
}

/*
 * 
 *    
    
       
   private static final String[] PROJECTION_PLACE = new String[] {
  Places._ID,
  Places.NAME,
  Places.TYPE,
  Places.STATE,
   };
       
   private static final String[] PROJECTION_WIFIFINGERPRINT = new String[] {
  Data._ID,
  Data.MIMETYPE,
  WifiFingerprint.FINGERPRINT,
  WifiFingerprint.TIMESTAMP,
   };
       
   private static final String[] PROJECTION_VISIT = new String[] {
  Visits._ID,
  Visits.ENTER,
  Visits.EXIT,
   };
       
   private Cursor mCursor;
    
mCursor = managedQuery(mUri, PROJECTION_PLACE, null, null, null);
    
if (mCursor.moveToFirst()) {
   do {
  long placeId = mCursor.getLong(mCursor.getColumnIndex(Places._ID));
  String name = mCursor.getString(mCursor.getColumnIndex(Places.NAME));
  int state = mCursor.getInt(mCursor.getColumnIndex(Places.STATE));
  Log.d(TAG, String.format("placeId=%d, name=%s, state=%d", placeId, name, state));
    
  Cursor dataC = managedQuery(Uri.parse(Places.CONTENT_URI + "/" + placeId + "/wifi"), PROJECTION_WIFIFINGERPRINT, null, null, null);
       
  if (dataC.moveToFirst()) {
     String wifi = dataC.getString(dataC.getColumnIndex(WifiFingerprint.FINGERPRINT));
     Log.d(TAG, wifi);
  }
      
  Uri visitUri = Uri.parse(Visits.CONTENT_URI + "/place/" + placeId);
  visitUri = visitUri.buildUpon().appendQueryParameter("limit", "1").build();
  Cursor visitsC = managedQuery(visitUri, PROJECTION_VISIT, null, null, null);
      
  if (visitsC.moveToFirst()) {
     long enter = visitsC.getLong(visitsC.getColumnIndex(Visits.ENTER));
     long exit = visitsC.getLong(visitsC.getColumnIndex(Visits.EXIT));
     Log.d(TAG, String.format("enter=%s exit=%s", MyDateUtils.getTimeFormatMedium(enter), MyDateUtils.getTimeFormatMedium(exit)));
  }
      
   } while (mCursor.moveToNext());
} else {
   Log.d(TAG, "mCursor is empty.");
}
    
*/