org.voidsink.anewjkuapp.update.ImportCalendarTask.java Source code

Java tutorial

Introduction

Here is the source code for org.voidsink.anewjkuapp.update.ImportCalendarTask.java

Source

/*
 *      ____.____  __.____ ___     _____
 *     |    |    |/ _|    |   \   /  _  \ ______ ______
 *     |    |      < |    |   /  /  /_\  \\____ \\____ \
 * /\__|    |    |  \|    |  /  /    |    \  |_> >  |_> >
 * \________|____|__ \______/   \____|__  /   __/|   __/
 *                  \/                  \/|__|   |__|
 *
 * Copyright (c) 2014-2015 Paul "Marunjar" Pretsch
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

package org.voidsink.anewjkuapp.update;

import android.Manifest;
import android.accounts.Account;
import android.app.SearchManager;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.SyncResult;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;

import net.fortuna.ical4j.data.CalendarBuilder;
//import net.fortuna.ical4j.extensions.groupwise.ShowAs;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.Component;
import net.fortuna.ical4j.model.Property;
import net.fortuna.ical4j.model.TimeZone;
import net.fortuna.ical4j.model.component.VEvent;

import org.voidsink.anewjkuapp.ImportPoiTask;
import org.voidsink.anewjkuapp.KusssContentContract;
import org.voidsink.anewjkuapp.Poi;
import org.voidsink.anewjkuapp.PoiContentContract;
import org.voidsink.anewjkuapp.R;
import org.voidsink.anewjkuapp.analytics.Analytics;
import org.voidsink.anewjkuapp.calendar.CalendarContractWrapper;
import org.voidsink.anewjkuapp.calendar.CalendarUtils;
import org.voidsink.anewjkuapp.kusss.KusssHandler;
import org.voidsink.anewjkuapp.notification.CalendarChangedNotification;
import org.voidsink.anewjkuapp.notification.SyncNotification;
import org.voidsink.anewjkuapp.utils.AppUtils;
import org.voidsink.anewjkuapp.utils.Consts;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ImportCalendarTask implements Callable<Void> {

    private static final String TAG = ImportCalendarTask.class.getSimpleName();

    private static final Object sync_lock = new Object();

    private final CalendarBuilder mCalendarBuilder;

    private static final Pattern courseIdTermPattern = Pattern.compile(KusssHandler.PATTERN_LVA_NR_SLASH_TERM);
    private static final Pattern lecturerPattern = Pattern.compile("Lva-LeiterIn:\\s+");

    private ContentProviderClient mProvider;
    private boolean mReleaseProvider = false;
    private final Account mAccount;
    private final SyncResult mSyncResult;
    private final Context mContext;
    private final String mCalendarName;
    private final ContentResolver mResolver;

    private final long mSyncFromNow;

    private boolean mShowProgress;
    private SyncNotification mUpdateNotification;

    public ImportCalendarTask(Account account, Context context, String getTypeID, CalendarBuilder calendarBuilder) {
        this(account, null, null, null, new SyncResult(), context, getTypeID, calendarBuilder);

        if (ContextCompat.checkSelfPermission(context,
                Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) {
            this.mProvider = context.getContentResolver()
                    .acquireContentProviderClient(CalendarContractWrapper.Events.CONTENT_URI());
        }
        this.mReleaseProvider = true;
        this.mShowProgress = true;
    }

    public ImportCalendarTask(Account account, Bundle extras, String authority, ContentProviderClient provider,
            SyncResult syncResult, Context context, String calendarName, CalendarBuilder calendarBuilder) {
        this.mAccount = account;
        this.mProvider = provider;
        this.mResolver = context.getContentResolver();
        this.mSyncResult = syncResult;
        this.mContext = context;
        this.mCalendarName = calendarName;
        this.mCalendarBuilder = calendarBuilder;
        this.mSyncFromNow = System.currentTimeMillis();
        this.mShowProgress = (extras != null && extras.getBoolean(Consts.SYNC_SHOW_PROGRESS, false));
    }

    private ContentValues getContentValuesFromEvent(VEvent v) {
        ContentValues cv = new ContentValues();

        cv.put(CalendarContractWrapper.Events.EVENT_LOCATION(), v.getLocation().getValue().trim());
        cv.put(CalendarContractWrapper.Events.TITLE(), v.getSummary().getValue().trim());
        cv.put(CalendarContractWrapper.Events.DESCRIPTION(), v.getDescription().getValue().trim());
        cv.put(CalendarContractWrapper.Events.DTSTART(), v.getStartDate().getDate().getTime());
        cv.put(CalendarContractWrapper.Events.DTEND(), v.getEndDate().getDate().getTime());

        return cv;
    }

    private void updateNotify(String string) {
        if (mUpdateNotification != null) {
            mUpdateNotification.update(string);
        }
    }

    private String getEventString(Context c, VEvent v) {
        return AppUtils.getEventString(c, v.getStartDate().getDate().getTime(), v.getEndDate().getDate().getTime(),
                v.getSummary().getValue().trim(), false);
    }

    @Override
    public Void call() throws Exception {
        if (mProvider == null) {
            return null;
        }

        if ((ContextCompat.checkSelfPermission(mContext,
                Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED)
                || (ContextCompat.checkSelfPermission(mContext,
                        Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED)) {
            return null;
        }

        if (!CalendarUtils.getSyncCalendar(mContext, this.mCalendarName)) {
            return null;
        }

        if (mShowProgress) {
            mUpdateNotification = new SyncNotification(mContext, R.string.notification_sync_calendar);
            mUpdateNotification.show(mContext.getString(R.string.notification_sync_calendar_loading,
                    CalendarUtils.getCalendarName(mContext, this.mCalendarName)));
        }
        CalendarChangedNotification mNotification = new CalendarChangedNotification(mContext,
                CalendarUtils.getCalendarName(mContext, this.mCalendarName));

        try {
            Log.d(TAG, "setup connection");

            updateNotify(mContext.getString(R.string.notification_sync_connect));

            if (KusssHandler.getInstance().isAvailable(mContext, AppUtils.getAccountAuthToken(mContext, mAccount),
                    AppUtils.getAccountName(mContext, mAccount), AppUtils.getAccountPassword(mContext, mAccount))) {

                updateNotify(mContext.getString(R.string.notification_sync_calendar_loading,
                        CalendarUtils.getCalendarName(mContext, this.mCalendarName)));

                Log.d(TAG, "loading calendar");

                Calendar iCal;
                String kusssIdPrefix;
                // {{ Load calendar events from resource
                switch (this.mCalendarName) {
                case CalendarUtils.ARG_CALENDAR_EXAM:
                    iCal = KusssHandler.getInstance().getExamIcal(mContext, mCalendarBuilder);
                    kusssIdPrefix = "at-jku-kusss-exam-";
                    break;
                case CalendarUtils.ARG_CALENDAR_COURSE:
                    iCal = KusssHandler.getInstance().getLVAIcal(mContext, mCalendarBuilder);
                    kusssIdPrefix = "at-jku-kusss-coursedate-";
                    break;
                default: {
                    Log.w(TAG, "calendar not found: " + this.mCalendarName);
                    return null;
                }
                }
                if (iCal == null) {
                    Log.w(TAG, "calendar not loaded: " + this.mCalendarName);
                    mSyncResult.stats.numParseExceptions++;
                    return null;
                }

                List<?> events = iCal.getComponents(Component.VEVENT);

                Log.d(TAG, String.format("got %d events", events.size()));

                updateNotify(mContext.getString(R.string.notification_sync_calendar_updating,
                        CalendarUtils.getCalendarName(mContext, this.mCalendarName)));

                ArrayList<ContentProviderOperation> batch = new ArrayList<>();

                // modify events: move courseId/term and lecturer to description
                String lineSeparator = System.getProperty("line.separator");
                if (lineSeparator == null)
                    lineSeparator = ", ";

                Map<String, VEvent> eventsMap = new HashMap<>();
                for (Object e : events) {
                    if (VEvent.class.isInstance(e)) {
                        VEvent ev = ((VEvent) e);

                        String summary = ev.getSummary().getValue().trim();
                        String description = ev.getDescription().getValue().trim();

                        Matcher courseIdTermMatcher = courseIdTermPattern.matcher(summary); // (courseId/term)
                        if (courseIdTermMatcher.find()) {
                            if (!description.isEmpty()) {
                                description += lineSeparator;
                                description += lineSeparator;
                            }
                            description += summary.substring(courseIdTermMatcher.start());
                            summary = summary.substring(0, courseIdTermMatcher.start());
                        } else {
                            Matcher lecturerMatcher = lecturerPattern.matcher(summary);
                            if (lecturerMatcher.find()) {
                                if (!description.isEmpty()) {
                                    description += lineSeparator;
                                    description += lineSeparator;
                                }
                                description += summary.substring(lecturerMatcher.start());
                                summary = summary.substring(0, lecturerMatcher.start());
                            }
                        }

                        summary = summary.trim().replaceAll("([\\r\\n]|\\\\n)+", ", ").trim();
                        description = description.trim();

                        ev.getProperty(Property.SUMMARY).setValue(summary);
                        ev.getProperty(Property.DESCRIPTION).setValue(description);
                    }
                }

                // Build hash table of incoming entries
                for (Object e : events) {
                    if (VEvent.class.isInstance(e)) {
                        VEvent ev = ((VEvent) e);

                        String uid = ev.getUid().getValue();
                        // compense DST
                        eventsMap.put(uid, ev);
                    }
                }

                String calendarId = CalendarUtils.getCalIDByName(mContext, mAccount, mCalendarName, true);

                if (calendarId == null) {
                    Log.w(TAG, "calendarId not found");
                    return null;
                }

                String mCalendarAccountName = mAccount.name;
                String mCalendarAccountType = mAccount.type;

                try {
                    Cursor c = mProvider.query(CalendarContractWrapper.Calendars.CONTENT_URI(),
                            CalendarUtils.CALENDAR_PROJECTION, null, null, null);
                    if (c != null) {
                        while (c.moveToNext()) {
                            if (calendarId.equals(c.getString(CalendarUtils.COLUMN_CAL_ID))) {
                                mCalendarAccountName = c.getString(CalendarUtils.COLUMN_CAL_ACCOUNT_NAME);
                                mCalendarAccountType = c.getString(CalendarUtils.COLUMN_CAL_ACCOUNT_TYPE);
                                break;
                            }
                        }
                        c.close();
                    }
                } catch (Exception e) {
                    return null;
                }

                Log.d(TAG, "Fetching local entries for merge with: " + calendarId);

                Uri calUri = CalendarContractWrapper.Events.CONTENT_URI();

                Cursor c = CalendarUtils.loadEvent(mProvider, calUri, calendarId);

                if (c == null) {
                    Log.w(TAG, "selection failed");
                } else {
                    Log.d(TAG, String.format("Found %d local entries. Computing merge solution...", c.getCount()));

                    // find stale data
                    String eventId;
                    String eventKusssId;
                    String eventLocation;
                    String eventTitle;
                    String eventDescription;
                    long eventDTStart;
                    long eventDTEnd;
                    boolean eventDirty;
                    boolean eventDeleted;

                    // calc date for notifiying only future changes
                    // max update interval is 1 week
                    long notifyFrom = new Date().getTime() - (DateUtils.DAY_IN_MILLIS * 7);

                    while (c.moveToNext()) {
                        mSyncResult.stats.numEntries++;
                        eventId = c.getString(CalendarUtils.COLUMN_EVENT_ID);

                        //                        Log.d(TAG, "---------");
                        eventKusssId = null;

                        // get kusssId from extended properties
                        Cursor c2 = mProvider.query(CalendarContract.ExtendedProperties.CONTENT_URI,
                                CalendarUtils.EXTENDED_PROPERTIES_PROJECTION,
                                CalendarContract.ExtendedProperties.EVENT_ID + " = ?", new String[] { eventId },
                                null);

                        if (c2 != null) {
                            while (c2.moveToNext()) {

                                //                                    String extra = "";
                                //                                    for (int i = 0; i < c2.getColumnCount(); i++) {
                                //                                        extra = extra + i + "=" + c2.getString(i) + ";";
                                //                                    }
                                //                                    Log.d(TAG, "Extended: " + extra);

                                if (c2.getString(1).contains(CalendarUtils.EXTENDED_PROPERTY_NAME_KUSSS_ID)) {
                                    eventKusssId = c2.getString(2);
                                }
                            }
                            c2.close();
                        }

                        if (TextUtils.isEmpty(eventKusssId)) {
                            eventKusssId = c.getString(CalendarUtils.COLUMN_EVENT_KUSSS_ID_LEGACY);
                        }

                        eventTitle = c.getString(CalendarUtils.COLUMN_EVENT_TITLE);
                        Log.d(TAG, "Title: " + eventTitle);

                        eventLocation = c.getString(CalendarUtils.COLUMN_EVENT_LOCATION);
                        eventDescription = c.getString(CalendarUtils.COLUMN_EVENT_DESCRIPTION);
                        eventDTStart = c.getLong(CalendarUtils.COLUMN_EVENT_DTSTART);
                        eventDTEnd = c.getLong(CalendarUtils.COLUMN_EVENT_DTEND);
                        eventDirty = "1".equals(c.getString(CalendarUtils.COLUMN_EVENT_DIRTY));
                        eventDeleted = "1".equals(c.getString(CalendarUtils.COLUMN_EVENT_DELETED));

                        if (eventKusssId != null && kusssIdPrefix != null
                                && eventKusssId.startsWith(kusssIdPrefix)) {
                            VEvent match = eventsMap.get(eventKusssId);
                            if (match != null && !eventDeleted) {
                                // Entry exists. Remove from entry
                                // map to prevent insert later
                                eventsMap.remove(eventKusssId);

                                // update only changes after notifiyFrom
                                if ((match.getStartDate().getDate().getTime() > notifyFrom
                                        || eventDTStart > notifyFrom) &&
                                // check to see if the entry needs to be updated
                                        ((match.getStartDate().getDate().getTime() != eventDTStart)
                                                || (match.getEndDate().getDate().getTime() != eventDTEnd)
                                                || (!match.getSummary().getValue().trim().equals(eventTitle.trim()))
                                                || (!match.getSummary().getValue().trim().equals(eventTitle.trim()))
                                                || (!match.getLocation().getValue().trim()
                                                        .equals(eventLocation.trim()))
                                                || (!match.getDescription().getValue().trim()
                                                        .equals(eventDescription.trim())))) {
                                    Uri existingUri = calUri.buildUpon().appendPath(eventId).build();

                                    // Update existing record
                                    Log.d(TAG, "Scheduling update: " + existingUri + " dirty=" + eventDirty);

                                    batch.add(ContentProviderOperation.newUpdate(existingUri)
                                            .withValues(getContentValuesFromEvent(match)).build());
                                    mSyncResult.stats.numUpdates++;

                                    mNotification.addUpdate(getEventString(mContext, match));
                                } else {
                                    mSyncResult.stats.numSkippedEntries++;
                                }
                            } else {
                                if (eventDTStart > (mSyncFromNow - DateUtils.DAY_IN_MILLIS)) {
                                    // Entry doesn't exist. Remove only newer events from the database.
                                    Uri deleteUri = calUri.buildUpon().appendPath(eventId).build();
                                    Log.d(TAG, "Scheduling delete: " + deleteUri);
                                    // notify only future changes
                                    if (eventDTStart > notifyFrom && !eventDeleted) {
                                        mNotification.addDelete(AppUtils.getEventString(mContext, eventDTStart,
                                                eventDTEnd, eventTitle, false));
                                    }

                                    batch.add(ContentProviderOperation.newDelete(deleteUri).build());
                                    mSyncResult.stats.numDeletes++;
                                } else {
                                    mSyncResult.stats.numSkippedEntries++;
                                }
                            }
                        } else {
                            Log.i(TAG, "Event UID not set, ignore event: uid=" + eventKusssId + " dirty="
                                    + eventDirty + " title=" + eventTitle);
                        }
                    }
                    c.close();

                    Log.d(TAG, String.format("Cursor closed, %d events left", eventsMap.size()));

                    updateNotify(mContext.getString(R.string.notification_sync_calendar_adding,
                            CalendarUtils.getCalendarName(mContext, this.mCalendarName)));

                    // Add new items
                    for (VEvent v : eventsMap.values()) {

                        if (v.getUid().getValue().startsWith(kusssIdPrefix)) {
                            // notify only future changes
                            if (v.getStartDate().getDate().getTime() > notifyFrom) {
                                mNotification.addInsert(getEventString(mContext, v));
                            }

                            Builder builder = ContentProviderOperation
                                    .newInsert(CalendarContractWrapper.Events.CONTENT_URI());

                            builder.withValue(CalendarContractWrapper.Events.CALENDAR_ID(), calendarId)
                                    .withValues(getContentValuesFromEvent(v))
                                    .withValue(CalendarContractWrapper.Events.EVENT_TIMEZONE(),
                                            TimeZone.getDefault().getID());

                            if (mCalendarName.equals(CalendarUtils.ARG_CALENDAR_EXAM)) {
                                builder.withValue(CalendarContractWrapper.Events.AVAILABILITY(),
                                        CalendarContractWrapper.Events.AVAILABILITY_BUSY());
                            } else {
                                builder.withValue(CalendarContractWrapper.Events.AVAILABILITY(),
                                        CalendarContractWrapper.Events.AVAILABILITY_FREE());
                            }

                            builder.withValue(CalendarContract.Events.STATUS,
                                    CalendarContract.Events.STATUS_TENTATIVE);
                            builder.withValue(CalendarContract.Events.HAS_ALARM, "0");
                            builder.withValue(CalendarContract.Events.HAS_ATTENDEE_DATA, "0");
                            builder.withValue(CalendarContract.Events.HAS_EXTENDED_PROPERTIES, "1");

                            ContentProviderOperation op = builder.build();
                            Log.d(TAG, "Scheduling insert: " + v.getUid().getValue());
                            batch.add(op);

                            int eventIndex = batch.size() - 1;

                            // add kusssid as extendet property
                            batch.add(ContentProviderOperation
                                    .newInsert(KusssContentContract.asEventSyncAdapter(
                                            CalendarContract.ExtendedProperties.CONTENT_URI, mAccount.name,
                                            mAccount.type))
                                    .withValueBackReference(CalendarContract.ExtendedProperties.EVENT_ID,
                                            eventIndex)
                                    .withValue(CalendarContract.ExtendedProperties.NAME,
                                            CalendarUtils.EXTENDED_PROPERTY_NAME_KUSSS_ID)
                                    .withValue(CalendarContract.ExtendedProperties.VALUE, v.getUid().getValue())
                                    .build());
                            // add location extra for google maps
                            batch.add(ContentProviderOperation
                                    .newInsert(KusssContentContract.asEventSyncAdapter(
                                            CalendarContract.ExtendedProperties.CONTENT_URI, mAccount.name,
                                            mAccount.type))
                                    .withValueBackReference(CalendarContract.ExtendedProperties.EVENT_ID,
                                            eventIndex)
                                    .withValue(CalendarContract.ExtendedProperties.NAME,
                                            CalendarUtils.EXTENDED_PROPERTY_LOCATION_EXTRA)
                                    .withValue(CalendarContract.ExtendedProperties.VALUE, getLocationExtra(v))
                                    .build());

                            mSyncResult.stats.numInserts++;
                        } else {
                            mSyncResult.stats.numSkippedEntries++;
                        }
                    }

                    if (batch.size() > 0) {
                        updateNotify(mContext.getString(R.string.notification_sync_calendar_saving,
                                CalendarUtils.getCalendarName(mContext, this.mCalendarName)));

                        Log.d(TAG, "Applying batch update");
                        mProvider.applyBatch(batch);
                        Log.d(TAG, "Notify resolver");
                        mResolver.notifyChange(calUri.buildUpon().appendPath(calendarId).build(), // URI
                                // where
                                // data
                                // was
                                // modified
                                null, // No local observer
                                false); // IMPORTANT: Do not sync to
                        // network
                    } else {
                        Log.w(TAG, "No batch operations found! Do nothing");
                    }
                }
                KusssHandler.getInstance().logout(mContext);
            } else {
                mSyncResult.stats.numAuthExceptions++;
            }
        } catch (Exception e) {
            Analytics.sendException(mContext, e, true);
            Log.e(TAG, "import calendar failed", e);
        }

        if (mUpdateNotification != null) {
            mUpdateNotification.cancel();
        }
        mNotification.show();

        if (mReleaseProvider) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                mProvider.close();
            } else {
                mProvider.release();
            }
        }

        return null;
    }

    private String getLocationExtra(VEvent event) {
        try {
            String name = event.getLocation().getValue().trim();

            String formattedAddress = "Altenbergerstrae 69, 4040 Linz, sterreich";
            double latitude = 48.33706;
            double longitude = 14.31960;
            String mapsClusterId = "CmRSAAAAEgnjqopJd0JVC22GrUK5G1fgukG3Q8gxwJ_4D-NdV1OZMP8oB3v_lA8GImeDVdqUR25xFAXHrRvR3QzA3U9i_OPDMh84Q0YFRX2IUXPhUTPfu1jp17f3APBlagpU-TNEEhAo0CzFCYccX9h60fY53upEGhROUkNAKVsKbGO2faMKyGvmc_26Ig";

            if (name != null) {
                if (name.toUpperCase().startsWith("PE 00")) {
                    formattedAddress = "Petrinumstrae 12, 4040 Linz, sterreich";
                    latitude = 48.319757;
                    longitude = 14.275298;
                    mapsClusterId = "CmRRAAAAVSgRGVv3PnjX7nWhyjLYOPA98MmrhhorKQHiTpKIALBSYkMMxTKTtvDr2KS3l6IKqhDqLicgeIwPl_uwmEN0aRokUojJa7Pryg-K7rLJ9ohiWXJow68suju9NfYzfJ3tEhDPlEQoguNvjwLjC8dXva7jGhTFyeDxDdfdZ8JY-dYjpPHqv_TXuQ";
                } else if (name.toUpperCase().startsWith("KEP ")) {
                    formattedAddress = "Altenbergerstrae 74, 4040 Linz, sterreich";
                    latitude = 48.3374066;
                    longitude = 14.324123;
                    mapsClusterId = "CmRSAAAA2F4LeVYCcAwT4VAT6mP3xqyDEZ40xdCIlUJZjJI0HRDrZYUTsCTrAQu0uXwdgE_Q2Yx-8kYiTg2XfA2pDpU5BkKgHfDKYPfh8_Zv6AiMgf9nxoAth1aUHlbp3iGMugauEhCUsVrMJImZyNojXWN_Nm8tGhQFqVEHQz2b5RCXc7cHik17JV1DCA";
                } else if (name.toUpperCase().startsWith("KHG ")) {
                    formattedAddress = "Mengerstrae 23, 4040 Linz, sterreich";
                    latitude = 48.33565830000001;
                    longitude = 14.3171069;
                    mapsClusterId = "CmRRAAAAzFi-w_zcsubNwMXG9-wpVfq6tFlTl2wxfR59QcybAQuF7k4kwNwTlFQWluOgyKKEtfi5-fP-zzJM_Jwv837jI-QTFQaDXfEpdaXKgHas9VNtHDjMbbTrh2YG5-8NZQz_EhAh0qirheebQ6QJROK39fNOGhQKPJEmyjv_S8iLlpIRtbskq_dThg";
                } else if (name.toUpperCase().startsWith("ESH ")) {
                    formattedAddress = "Julius-Raab-Strae 1-3, 4040 Linz, sterreich";
                    latitude = 48.32893189999999;
                    longitude = 14.3220179;
                    mapsClusterId = "CmRRAAAAztw2Q-pFchJnT32wqealtHgsRyNlzebFxGqFb_PZIRsqujQKfTNKYn0zA6mdGYelwDtmm-SIKH5srpkIGrZkwhckuYQhFo3UkpLsnFYV73hScFdrSvMJLmGuKLwRHW1bEhBTuKPtU_mvcMQplpxK-h6PGhSnVtoLUH37vZBXvWna051K_nC5PA";
                }

                ContentResolver cr = mContext.getContentResolver();
                Uri searchUri = PoiContentContract.CONTENT_URI.buildUpon()
                        .appendPath(SearchManager.SUGGEST_URI_PATH_QUERY).appendPath(name).build();
                Cursor c = cr.query(searchUri, ImportPoiTask.POI_PROJECTION, null, null, null);
                Poi p = null;

                if (c != null) {
                    while (c.moveToNext()) {
                        p = new Poi(c);

                        if (p.getName().equalsIgnoreCase(name)) {
                            break;
                        }
                        p = null;
                    }
                    c.close();
                }

                if (p != null) {
                    latitude = p.getLat();
                    longitude = p.getLon();
                    name = p.getName();
                }
            } else {
                name = "";
            }

            DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
            dfs.setDecimalSeparator('.');
            DecimalFormat df = new DecimalFormat("##0.0#############", dfs);

            return String.format(
                    "{\"locations\":[{\"address\":{\"formattedAddress\":\"%s\"},\"geo\":{\"latitude\":%s,\"longitude\":%s},\"mapsClusterId\":\"%s\",\"name\":\"%s\",\"url\":\"http://maps.google.com/maps?q=loc:%s,%s+(%s)&z=19\n\"}]}",
                    formattedAddress, df.format(latitude), df.format(longitude), mapsClusterId, name,
                    df.format(latitude), df.format(longitude), name);
        } catch (Exception e) {
            Analytics.sendException(mContext, e, true);
            return "";
        }
    }
}