package org.wheelmap.android.fragment; import org.wheelmap.android.app.WheelmapApp; import org.wheelmap.android.fragment.SearchDialogFragment.OnSearchDialogListener; import org.wheelmap.android.manager.MyLocationManager; import org.wheelmap.android.mapping.node.Node; import org.wheelmap.android.model.Extra; import org.wheelmap.android.model.Extra.What; import org.wheelmap.android.model.POIsCursorWrapper; import org.wheelmap.android.model.UserQueryHelper; import org.wheelmap.android.model.Wheelmap.POIs; import org.wheelmap.android.online.R; import org.wheelmap.android.service.RestService; import org.wheelmap.android.service.RestServiceException; import org.wheelmap.android.service.RestServiceHelper; import org.wheelmap.android.utils.DetachableResultReceiver; import org.wheelmap.android.utils.DetachableResultReceiver.Receiver; import android.app.Activity; import android.app.SearchManager; import android.content.ContentValues; import android.database.Cursor; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.widget.Toast; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import java.math.BigDecimal; import java.util.HashSet; import java.util.Set; import de.akquinet.android.androlog.Log; import de.greenrobot.event.EventBus; public class CombinedWorkerFragment extends Fragment implements WorkerFragment, Receiver, LoaderCallbacks<Cursor>, OnSearchDialogListener { public final static String TAG = CombinedWorkerFragment.class .getSimpleName(); Set<DisplayFragment> mListener = new HashSet<DisplayFragment>(); public final static int LOADER_LIST_ID = 0; public final static int LOADER_MAP_ID = 1; private final static float QUERY_DISTANCE_DEFAULT = 0.8f; private WorkerFragmentListener mFragmentListener; private DetachableResultReceiver mReceiver; private Cursor mListCursor; private Cursor mMapCursor; boolean isSearchMode; private boolean mRefreshStatus; private EventBus mBus; private Location mLocation; private String mUserQuery; @Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof WorkerFragmentListener) { mFragmentListener = (WorkerFragmentListener) activity; } mBus = EventBus.getDefault(); mBus.register(this); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); mReceiver = new DetachableResultReceiver(new Handler()); mReceiver.setReceiver(this); requestUpdate(null); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.d(TAG, "starting both loaders"); getLoaderManager().initLoader(LOADER_LIST_ID, null, this); getLoaderManager().initLoader(LOADER_MAP_ID, null, this); } @Override public void onDetach() { super.onDetach(); mBus.post(new MyLocationManager.UnregisterEvent()); mBus.unregister(this); } @Override public void onDestroy() { super.onDestroy(); mReceiver.clearReceiver(); } @Override public void registerDisplayFragment(DisplayFragment fragment) { mListener.add(fragment); } @Override public void unregisterDisplayFragment(DisplayFragment fragment) { mListener.remove(fragment); } private void setRefreshStatus(boolean refreshState) { mRefreshStatus = refreshState; update(); } public void update() { for (DisplayFragment fragment : mListener) { fragment.onUpdate(this); } } @Override public void requestUpdate(Bundle bundle) { if (isSearchMode) { return; } Log.d(TAG, "resuestUpdate: " + bundle); if (bundle == null) { WheelmapApp app = (WheelmapApp) this.getActivity().getApplication(); String uri = null; try{ uri = app.getUriString(); }catch (Exception ex){} if(uri != null){ // load one node, then all others near by this node RestServiceHelper.retrieveNode(getActivity(),uri,mReceiver); } else{ LocationManager myLocationManager = (LocationManager) getActivity().getSystemService( WheelmapApp.getApp().LOCATION_SERVICE); if(LocationManager.PASSIVE_PROVIDER != null && !LocationManager.PASSIVE_PROVIDER.equals("null")){ mLocation = myLocationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); } RestServiceHelper.retrieveNodesByDistance(getActivity(), mLocation, QUERY_DISTANCE_DEFAULT, mReceiver); } } else { WheelmapApp app = null; Node node = null; try{ app = (WheelmapApp) this.getActivity().getApplication(); }catch(NullPointerException npex){ Log.d("Tag:CombinedWorkerFragment", "NullPointException occurred"); Toast.makeText(this.getActivity().getApplicationContext(), getResources().getString(R.string.error_internal_error), Toast.LENGTH_LONG).show(); } try{ node = app.getNode(); }catch (Exception ex){ Log.d("Tag:CombinedWorkerFragment", "NullPointException occurred"); Toast.makeText(this.getActivity().getApplicationContext(),getResources().getString(R.string.error_internal_error) , Toast.LENGTH_LONG).show(); } if(node == null){ bundle.putInt(Extra.WHAT, What.RETRIEVE_NODES); bundle.putParcelable(Extra.STATUS_RECEIVER, mReceiver); RestServiceHelper.executeRequest(getActivity(), bundle); } } } public ContentValues getValues(Node node){ ContentValues values = new ContentValues(19); values.put("nodetype_identifier",node.getNodeType().getIdentifier()); values.put("icon",node.getIcon()); values.put("phone", node.getPhone()); values.put("website",node.getWebsite()); values.put("street",node.getStreet()); values.put("category_id",node.getCategory().getId().toString()); values.put("postcode",node.getPostcode()); values.put("house_num",node.getHousenumber()); values.put("city",node.getCity()); values.put("category_identifier",node.getCategory().getIdentifier()); values.put("nodetype_id", node.getNodeType().getId().toString()); values.put("wheelchair",node.getWheelchair()); values.put("wheelchair_toilet",node.getWheelchairToilet()); values.put("description",node.getWheelchairDescription()); values.put("name",node.getName()); values.put(POIs.LONGITUDE,node.getLon().toString()); values.put(POIs.LATITUDE, node.getLat().toString()); values.put("wm_id",node.getId().toString()); return values; } @Override public void onSearch(Bundle bundle) { Log.d(TAG, "requestSearch with bundle " + bundle.toString()); if (bundle.containsKey(Extra.ENABLE_BOUNDING_BOX)) { Fragment f = (Fragment) getFragmentManager().findFragmentByTag( POIsOsmdroidFragment.TAG); ((OnSearchDialogListener) f).onSearch(bundle); } requestSearch(bundle); } @Override public void requestSearch(Bundle bundle) { if (!bundle.containsKey(SearchManager.QUERY) && !bundle.containsKey(Extra.CATEGORY) && !bundle.containsKey(Extra.NODETYPE) && !bundle.containsKey(Extra.WHEELCHAIR_STATE) && !bundle.containsKey(Extra.WHEELCHAIR_TOILET_STATE)) { return; } if (bundle.getInt(Extra.CATEGORY) == Extra.UNKNOWN) { bundle.remove(Extra.CATEGORY); } if (!bundle.containsKey(Extra.WHAT)) { int what; if (bundle.containsKey(Extra.CATEGORY) || bundle.containsKey(Extra.NODETYPE)) { what = What.RETRIEVE_NODES; } else { what = What.SEARCH_NODES; } bundle.putInt(Extra.WHAT, what); } if (bundle.containsKey(Extra.BOUNDING_BOX)) { // noop } else if (bundle.containsKey(Extra.DISTANCE_LIMIT)) { bundle.putParcelable(Extra.LOCATION, mLocation); bundle.remove(Extra.BOUNDING_BOX); } bundle.putParcelable(Extra.STATUS_RECEIVER, mReceiver); RestServiceHelper.executeRequest(getActivity(), bundle); setSearchModeInt(true); } @Override public Cursor getCursor(int id) { if (id == LIST_CURSOR) { return mListCursor; } else if (id == MAP_CURSOR) { return mMapCursor; } else { throw new IllegalArgumentException("Cursor id not available "); } } @Override public boolean isRefreshing() { return mRefreshStatus; } @Override public boolean isSearchMode() { return isSearchMode; } private void setSearchModeInt(boolean searchMode) { Log.d(TAG, "setSearchMode: " + searchMode); isSearchMode = searchMode; if (mFragmentListener != null) { mFragmentListener.onSearchModeChange(isSearchMode); } update(); } @Override public void setSearchMode(boolean searchMode) { Log.d(TAG, "setSearchMode: " + isSearchMode); isSearchMode = searchMode; update(); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { mUserQuery = UserQueryHelper.INSTANCE.getUserQuery(); if (id == LOADER_MAP_ID) { Uri uri = POIs.CONTENT_URI_RETRIEVED; return new CursorLoader(getActivity(), uri, POIs.PROJECTION, mUserQuery, null, null); } else { return new CursorLoader(getActivity(), POIs.createUriSorted(mLocation), POIs.PROJECTION, mUserQuery, null, null); } } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { if (loader.getId() == LOADER_MAP_ID) { mMapCursor = cursor; } else { Cursor wrappingCursor = new POIsCursorWrapper(cursor, mLocation); Log.d(TAG, "cursorloader - new cursor - cursor size = " + wrappingCursor.getCount()); mListCursor = wrappingCursor; } update(); } @Override public void onLoaderReset(Loader<Cursor> loader) { Log.d(TAG, "onLoaderReset - need to set it to null"); if (loader.getId() == LOADER_MAP_ID) { mMapCursor = null; } else { mListCursor = null; } update(); } private void resetCursorLoaderUri() { Loader<Cursor> loader = getLoaderManager().getLoader(LOADER_LIST_ID); if (loader == null) { return; } CursorLoader cl = (CursorLoader) loader; cl.setUri(POIs.createUriSorted(mLocation)); loader.forceLoad(); } public void onResume(){ super.onResume(); mReceiver = new DetachableResultReceiver(new Handler()); mReceiver.setReceiver(this); getLoaderManager().restartLoader(LOADER_LIST_ID, new Bundle(), this); getLoaderManager().restartLoader(LOADER_MAP_ID, new Bundle(), this); } /** * {@inheritDoc} */ public void onReceiveResult(int resultCode, Bundle resultData) { Log.d(TAG, "onReceiveResult resultCode = " + resultCode); switch (resultCode) { case RestService.STATUS_RUNNING: { setRefreshStatus(true); break; } case RestService.STATUS_FINISHED: { WheelmapApp app = WheelmapApp.getApp(); if(app != null){ if(resultData.get("WHAT").equals(What.SEARCH_NODES)){ if(app.isSearchSuccessfully() == false){ app.setSearchSuccessfully(true); CharSequence text = getString(R.string.search_mode_no_point_found); int duration = Toast.LENGTH_LONG; Toast toast = Toast.makeText(app, text, duration); toast.show(); } } if(resultData.get("WHAT").equals(What.RETRIEVE_NODE)){ Node node = null; try{ node = app.getNode(); }catch (Exception ex){ // noop } if(node != null){ BigDecimal bdlat = node.getLat(); BigDecimal bdlon = node.getLon(); double dlat = bdlat.doubleValue(); double dlon = bdlon.doubleValue(); app.setNode(null); app.setUriString(null); for (DisplayFragment fragment : mListener) { if(fragment.getClass().toString().equals("class org.wheelmap.android.fragment.POIsOsmdroidFragment")){ ContentValues cv = getValues(node); ((POIsOsmdroidFragment) fragment).markItem(cv,true); ((POIsOsmdroidFragment)fragment).requestUpdate(); } } mLocation = new Location("reverseGeocoded"); mLocation.setLatitude(dlat); mLocation.setLongitude(dlon); mLocation.setAccuracy(3333); mLocation.setBearing(333); RestServiceHelper.retrieveNodesByDistance(getActivity(),mLocation,QUERY_DISTANCE_DEFAULT,mReceiver); } } if(resultData.get("WHAT").equals(What.RETRIEVE_NODES)){ double lat = 0; double lon = 0; lat = app.getGeoLat(); lon = app.getGeoLon(); if(lat != 0 && lon != 0){ app.setGeoLat(0); app.setGeoLon(0); app.setNoItemToSelect(true); for (DisplayFragment fragment : mListener) { if(fragment.getClass().toString().equals("class org.wheelmap.android.fragment.POIsOsmdroidFragment")){ ContentValues cv = new ContentValues(2); cv.put(POIs.LATITUDE, lat); cv.put(POIs.LONGITUDE, lon); ((POIsOsmdroidFragment) fragment).markItem(cv, true); ((POIsOsmdroidFragment)fragment).requestUpdate(); } } mLocation = new Location("reverseGeocoded"); mLocation.setLatitude(lat); mLocation.setLongitude(lon); mLocation.setAccuracy(3333); mLocation.setBearing(333); RestServiceHelper.retrieveNodesByDistance(getActivity(),mLocation,QUERY_DISTANCE_DEFAULT,mReceiver); } } } setRefreshStatus(false); break; } case RestService.STATUS_ERROR: { setRefreshStatus(false); RestServiceException e = resultData.getParcelable(Extra.EXCEPTION); if (mFragmentListener != null) { mFragmentListener.onError(e); } break; } } } public void onEventMainThread(MyLocationManager.LocationEvent locationEvent) { Log.d(TAG, "updateLocation"); mLocation = locationEvent.location; resetCursorLoaderUri(); } public void onEventMainThread(UserQueryHelper.UserQueryUpdateEvent e) { Log.d(TAG, "onUserQueryChanged: received event: Query"+e.query); mUserQuery = e.query; getLoaderManager().restartLoader(LOADER_LIST_ID, new Bundle(), this); getLoaderManager().restartLoader(LOADER_MAP_ID, new Bundle(), this); } }