yasme/src/main/java/de/fau/cs/mad/yasme/android/entities/Chat.java
@JsonIgnoreProperties(ignoreUnknown = true)
@DatabaseTable(tableName = DatabaseConstants.CHAT_TABLE)
public class Chat implements Serializable {

    @DatabaseField(columnName = DatabaseConstants.CHAT_ID, id = true)
    private long id;

    private List<User> participants;

    @DatabaseField(columnName = DatabaseConstants.NAME_CHANGED)
    private boolean nameChanged = false;

    @DatabaseField(columnName = DatabaseConstants.STATUS_CHANGED)
    private boolean statusChanged = false;

    @DatabaseField(columnName = DatabaseConstants.CHAT_STATUS)
    private String status;

    @DatabaseField(columnName = DatabaseConstants.CHAT_NAME)
    private String name;

    @DatabaseField(columnName = DatabaseConstants.OWNER, foreign = true)
    private User owner;

    @DatabaseField(columnName = DatabaseConstants.CHAT_LAST_MODIFIED, dataType = DataType.DATE)
    private Date lastModified;

    @DatabaseField(columnName = DatabaseConstants.CHAT_CREATED)
    private Date created;

    @JsonIgnore
    private String profilePicture;

    @JsonIgnore
    @ForeignCollectionField(columnName = DatabaseConstants.MESSAGES)
    private Collection<Message> messages;

    @JsonIgnore
    @DatabaseField(columnName = DatabaseConstants.LAST_MESSAGE, foreign = true)
    private Message lastMessage;

    /**
     * Constructors *
     */
    public Chat(long id) {
        this.id = id;
        this.participants = new ArrayList<User>();
        this.messages = new ArrayList<Message>();
    }

    /**
     * It is needed to set an id after calling this constructor!
     *
     * @param owner
     * @param status
     * @param name
     */
    public Chat(User owner, String status, String name) {
        new Chat(0, new ArrayList<User>(), status, name, owner, new ArrayList<Message>());
    }

    public Chat(long id, List<User> participants, String status, String name,
                User owner) {
        new Chat(id, participants, status, name, owner, new ArrayList<Message>());
    }

    public Chat() {
        // ORMLite needs a no-arg constructor
    }

    public Chat(long id, List<User> participants, String status, String name, User owner,
                Collection<Message> messages) {
        this.id = id;
        this.participants = participants;
        this.status = status;
        this.name = name;
        this.owner = owner;
        this.messages = messages;
    }

    public Chat(Chat origin) throws IllegalAccessException {
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.set(this, field.get(origin));
        }
    }

    /**
     * Getters *
     */
    public long getId() {
        return id;
    }

    /**
     * Setters *
     */
    public void setId(long id) {
        this.id = id;
    }

    public int size() {
        if (null == participants) {
            Log.e(((Object) this).getClass().getSimpleName(), "Participants are null");
            return -1;
        }
        return participants.size();
    }

    @JsonIgnoreProperties({"pw", "email", "name", "devices", "lastModified", "created"})
    public ArrayList<User> getParticipants() {
        if (participants == null) {
            participants = new ArrayList<>();
            User mDummy = new User("Dummy", 12);
            participants.add(mDummy);
            // Without cast IntelliJ is not happy
            Log.e(((Object) this).getClass().getSimpleName(), "Participants are null");
        }
        return new ArrayList<User>(participants);
    }

    public void setParticipants(List<User> participants) {
        this.participants = participants;
    }

    public void setNameChanged(boolean nameChanged) {
        this.nameChanged = nameChanged;
    }

    public void setStatusChanged(boolean statusChanged) {
        this.statusChanged = statusChanged;
    }

    public boolean addParticipant(User newUser) {
        if (participants == null) {
            Log.e(((Object) this).getClass().getSimpleName(), "Participants are null");
            return false;
        }
        participants.add(newUser);
        return true;
    }

    public boolean removeParticipant(User delUser) {
        if (participants == null) {
            Log.e(((Object) this).getClass().getSimpleName(), "Participants are null, sry.");
            return false;
        }
        boolean ret = false;
        for (User u : participants) {
            if (u.getId() != delUser.getId()) {
                continue;
            }
            ret = participants.remove(u);
            break;
        }
        return true;
    }

    public String getStatus() {
        if (!this.statusChanged || this.status == null || this.status.isEmpty()) {
            return (getNumberOfParticipants() + " YASMEs");
        }
        return this.status;
    }

    public void setStatus(String status, boolean isNotDefault) {
        this.statusChanged = isNotDefault;
        this.status = status;
    }

    public boolean getStatusChanged() {
        return this.statusChanged;
    }

    public boolean getNameChanged() {
        return this.nameChanged;
    }

    @JsonProperty("name")
    public String getName() {
        if (this.nameChanged && this.name != null && this.name.length() > 0) {
            return name;
        }
        // Create a new name
        String returnName = "";
        try {
            int size = getParticipants().size();
            for (int i = 0; i < size; i++) {
                returnName += participants.get(i).getName();
                if (i < size - 1) {
                    returnName += ", ";
                }
            }
        } catch (Exception e) {
            Log.d(this.getClass().getSimpleName(), e.getMessage());
        }
        return returnName;
    }

    public void setName(String name, boolean isNotDefault) {
        this.nameChanged = isNotDefault;
        this.name = name;
    }

    public Date getLastModified() {
        return lastModified;
    }

    public void setLastModified(Timestamp lastModified) {
        this.lastModified = lastModified;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Timestamp created) {
        this.created = created;
    }

    public String getProfilePicture() {
        return profilePicture;
    }

    public void setProfilePicture(String profilePicture) {
        this.profilePicture = profilePicture;
    }

    @JsonIgnoreProperties({"pw", "email", "name", "devices", "lastModified", "created"})
    public User getOwner() {
        if (owner == null) {
            owner = new User("Dummy", 12);
        }
        return owner;
    }

    public void setOwner(User owner) {
        this.owner = owner;
    }

    @JsonIgnore
    public int getNumberOfParticipants() {
        if (participants != null) {
            return participants.size();
        }
        return 0;
    }

    @JsonIgnore
    public ArrayList<Message> getMessages() {
        if (messages == null) {
            return new ArrayList<Message>();
        }
        return new ArrayList<Message>(messages);
    }

    public void setMessages(ArrayList<Message> messages) {
        this.messages = messages;
    }

    public void setLastModified(Date lastModified) {
        this.lastModified = lastModified;
    }

    /**
     * Other Methods
     */
    @JsonIgnore
    public boolean isOwner(long userId) {
        if (owner.getId() == userId) {
            return true;
        }
        return false;
    }

    public Message getLastMessage() {
        return lastMessage;
    }

    public void setLastMessage(Message lastMessage) {
        this.lastMessage = lastMessage;
    }

    public Chat clone() {
        try {
            return new Chat(this);
        } catch (IllegalAccessException e) {
            Log.e(this.getClass().getSimpleName(), e.getMessage());
            return null;
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/controller/NotifiableFragment.java
public interface NotifiableFragment<T> {

    void notifyFragment(T value);
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/asyncTasks/server/ChangeOwnerAndLeaveTask.java
public class ChangeOwnerAndLeaveTask extends AsyncTask<Long, Void, Boolean> {
    private Chat chat;

    public ChangeOwnerAndLeaveTask(Chat chat) {
        this.chat = chat;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        SpinnerObservable.getInstance().registerBackgroundTask(this);
    }

    /**
     * @param params 0 is id of new owner
     *               1 is additional leave
     * @return Returns true if it was successful, otherwise false
     */
    @Override
    protected Boolean doInBackground(Long... params) {
        try {
            ChatTask.getInstance().changeOwnerOfChat(chat.getId(), params[0]);
        } catch (RestServiceException e) {
            Log.e(this.getClass().getSimpleName(), e.getMessage());
            return false;
        }
        chat.setOwner(DatabaseManager.INSTANCE.getUserDAO().get(params[0]));
        if (params[1] == 1L) {
            try {
                ChatTask.getInstance().removeOneSelfFromChat(chat.getId());
            } catch (RestServiceException e) {
                Log.e(this.getClass().getSimpleName(), e.getMessage());
                return false;
            }
            chat.removeParticipant(DatabaseManager.INSTANCE.getUserDAO()
                    .get(DatabaseManager.INSTANCE.getUserId()));
        }
        DatabaseManager.INSTANCE.getChatDAO().update(chat);
        return true;
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        SpinnerObservable.getInstance().removeBackgroundTask(this);
        if (success) {
            Toaster.getInstance().toast(R.string.change_successful, Toast.LENGTH_LONG);
            new GetMyChatsTask(ChatListFragment.class).startIfNecessary();
        } else {
            Toaster.getInstance().toast(R.string.change_not_successful, Toast.LENGTH_LONG);
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/EditTextWithX.java
public class EditTextWithX {
    private EditText et;
    private Drawable x;

    public EditTextWithX(Context context) {
        et = new EditText(context);
        x = context.getResources().getDrawable(R.drawable.ic_action_cancel);
        x.setBounds(0, 0, x.getIntrinsicWidth(), x.getIntrinsicHeight());
        et.setCompoundDrawables(null, null, et.getText().toString().equals("") ? null : x, null);
        et.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (et.getCompoundDrawables()[2] == null) {
                    return false;
                }
                if (motionEvent.getAction() != MotionEvent.ACTION_UP) {
                    return false;
                }
                if (motionEvent.getX() > et.getWidth() - et.getPaddingRight() - x.getIntrinsicWidth()) {
                    et.setText("");
                    et.setCompoundDrawables(null, null, null, null);
                }
                return false;
            }
        });
        et.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                et.setCompoundDrawables(null, null, et.getText().toString().equals("") ? null : x, null);
            }

            @Override
            public void afterTextChanged(Editable arg0) {

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }
        });
    }

    public EditText getEditText() {
        return et;
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/ui/UserAdapter.java
public class UserAdapter extends ArrayAdapter<User> {
    private List<User> users;
    private final Context context;
    private SparseBooleanArray selectedContacts = new SparseBooleanArray();
    private int layout = R.layout.user_item;

    public SparseBooleanArray getSelectedContacts() {
        return selectedContacts;
    }

    /**
     * @see <a href="http://developer.android.com/design/style/color.html">Color palette used</a>
     * from K9 Mail
     */
    public final static int CONTACT_DUMMY_COLORS_ARGB[] = {
            0xff33B5E5,
            0xffAA66CC,
            0xff99CC00,
            0xffFFBB33,
            0xffFF4444,
            0xff0099CC,
            0xff9933CC,
            0xff669900,
            0xffFF8800,
            0xffCC0000
    };

    public UserAdapter(Context context, int resource, List<User> users) {
        super(context, resource, users);
        this.users = users;
        this.context = context;
        this.layout = resource;
    }

    @Override
    public void notifyDataSetChanged() {
        selectedContacts = new SparseBooleanArray();
        super.notifyDataSetChanged();
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        User user = DatabaseManager.INSTANCE.getUserDAO().get(users.get(position).getId());
        if (user == null) {
            Log.w(this.getClass().getSimpleName(), "User not found in DB");
            user = users.get(position);
        }

        LayoutInflater inflater = ((Activity) context).getLayoutInflater();

        View rowView = inflater.inflate(layout, parent, false);

        ImageView profileImage = (ImageView) rowView.findViewById(R.id.user_picture);
        TextView initial = (TextView) rowView.findViewById(R.id.user_picture_text);
        TextView profileName = (TextView) rowView.findViewById(R.id.user_name);
        TextView profileId = (TextView) rowView.findViewById(R.id.user_id);
        CheckBox checkBox;
        if (layout == R.layout.user_item_checkbox) {
            checkBox = (CheckBox) rowView.findViewById(R.id.checkBox);
        } else {
            checkBox = null;
        }

        boolean isSelf = (user.getId() == DatabaseManager.INSTANCE.getUserId());
        if (isSelf) {
            SharedPreferences storage = context
                    .getSharedPreferences(AbstractYasmeActivity.STORAGE_PREFS, Context.MODE_PRIVATE);
            user.setProfilePicture(storage.getString(AbstractYasmeActivity.PROFILE_PICTURE, null));
        }

        if (user.getProfilePicture() != null && !user.getProfilePicture().isEmpty()) {
            // load picture from local storage
            initial.setVisibility(View.GONE);
            profileImage.setBackgroundColor(Color.TRANSPARENT);
            profileImage.setImageBitmap(PictureManager.INSTANCE.getPicture(user, 50, 50));
        } else {
            // no local picture found. Set default pic
            profileImage.setBackgroundColor(CONTACT_DUMMY_COLORS_ARGB
                    [(int) user.getId() % CONTACT_DUMMY_COLORS_ARGB.length]);
            initial.setText(user.getName().substring(0, 1).toUpperCase());
        }

        profileName.setText(user.getName());
        profileId.setText("YD " + user.getId());
        if (checkBox != null) {
            checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    selectedContacts.append(position, b);
                }
            });
        }

        rowView.requestFocus();
        return rowView;
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/storage/dao/ChatDAO.java
public interface ChatDAO extends DAO<Chat> {

    /**
     * Creates a chat item but only if the ID does not already exist in the table. This
     * extracts the id from the chat parameter, queries for it's id, returning the data if it
     * exists. If it does not exist create will be called with the parameter.
     * @param chat to be added
     * @return given chat or null if an error occurs
     */
    public Chat addIfNotExists(Chat chat);


    /**
     * This method is a combination of addIfNotExists and update for the sake of convenience.
     * Queries for a chat item with the specified id. If there is none, addIfNotExists is called, otherwise update.
     * @param chat to be added or updated
     * @return given chat after insertion / update
     */
    public Chat addOrUpdate(Chat chat);

    /**
     * Retrieves an object associated with a specific ID.
     * @param id Identifier that matches a specific row in the database to find and return.
     * @return The object that has the ID field which equals id or null if no matches.
     */
    public Chat get(long id);

    /**
     * Query for all of the items in the object table
     * @return list of all chats or null on error
     */
    public List<Chat> getAll();


    /**
     * Retrieves all chats from the database which are held between the exact list of given users
     * @param users who participate in the chat to return. Don't forget that you are a participant as well and thus should be present in the list
     * @return list of chats which matched the conditions
     */
    public List<Chat> getByParticipantsExact(Set<User> users);


    /**
     * Retrieves all chats from the database which are held between the given users or more
     * @param users who participate in the chat to look for
     * @return list of chats which have the given users (and more) as participants
     */
    public List<Chat> getByTheseParticipantsOrMore(Set<User> users);

    /**
     * Store the fields from an object to the database row corresponding to the id from the data parameter. If you have
     * made changes to an object, this is how you persist those changes to the database. You cannot use this method to
     * update the id field
     * @param chat to be updated
     * @return given chat or null on error
     */
    public Chat update(Chat chat);


    /**
     * Delete the database row corresponding to the id from the data parameter.
     * @param chat to be deleted
     * @return true on success, false otherwise
     */
    public boolean delete(Chat chat);


    /**
     * Replaces all currently stored chats with given ones. Updates old chats with the values from the new one if their id matches.
     * @param newChats to be stored
     * @return true if successful, false otherwise
     */
    public boolean refreshAll(List<Chat> newChats);
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/asyncTasks/server/LeaveChatTask.java
public class LeaveChatTask extends AsyncTask<Long, Void, Boolean> {
    private Chat chat;

    public LeaveChatTask(Chat chat) {
        this.chat = chat;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        SpinnerObservable.getInstance().registerBackgroundTask(this);
    }

    /**
     * @return true an success, otherwise false
     */
    @Override
    protected Boolean doInBackground(Long... params) {
        try {
            ChatTask.getInstance().removeOneSelfFromChat(chat.getId());
        } catch (RestServiceException e) {
            Log.e(this.getClass().getSimpleName(), e.getMessage());
            return false;
        }
        return true;
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        SpinnerObservable.getInstance().removeBackgroundTask(this);
        if (success) {
            Toaster.getInstance().toast(R.string.change_successful, Toast.LENGTH_SHORT);
            new GetMyChatsTask(ChatListFragment.class).startIfNecessary();
        } else {
            Toaster.getInstance().toast(R.string.change_not_successful, Toast.LENGTH_SHORT);
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/storage/DatabaseManager.java
public enum DatabaseManager {
    INSTANCE;

    private boolean mInitialized = false;
    private boolean mDBInitialized = false;
    private DatabaseHelper mHelper;
    private Context mContext;
    private long mUserId = -1;
    private long mDeviceId = -1;
    private String mAccessToken = null;
    private long serverInfoUpdateTime = -1;
    private ServerInfo serverInfo = null;
    private SharedPreferences mSharedPreferences, mSettings;
    private String mUserEmail;
    private NewMessageNotificationManager notifier = null;

    private UserDAO userDAO;
    private ChatDAO chatDAO;
    private MessageDAO messageDAO;
    private MessageKeyDAO messageKeyDAO;
    private DeviceDAO deviceDAO;


    public void init(Context context, SharedPreferences sharedPreferences,
                     SharedPreferences settings, long userId) {
        mContext = context;
        mSharedPreferences = sharedPreferences;
        mSettings = settings;
        mUserId = userId;
        initDB(context, userId);
        initializeDAOs();
        mInitialized = true;
    }

    public void initDB(Context context, long userId) {
        mHelper = new DatabaseHelper(context, userId);
        mDBInitialized = true;
    }

    public boolean isInitialized() {
        return mInitialized;
    }

    public boolean isDBInitialized() {
        return mDBInitialized;
    }

    private DatabaseHelper getHelper() {
        return mHelper;
    }

    public SharedPreferences getSharedPreferences() {
        return mSharedPreferences;
    }

    public SharedPreferences getSettings() {
        return mSettings;
    }

    public Context getContext() {
        return mContext;
    }

    private void initializeDAOs() {
        UserDAOImpl.INSTANCE.setDatabaseHelper(mHelper);
        userDAO = UserDAOImpl.INSTANCE;

        ChatDAOImpl.INSTANCE.setDatabaseHelper(mHelper);
        chatDAO = ChatDAOImpl.INSTANCE;

        MessageDAOImpl.INSTANCE.setDatabaseHelper(mHelper);
        messageDAO = MessageDAOImpl.INSTANCE;

        MessageKeyDAOImpl.INSTANCE.setDatabaseHelper(mHelper);
        messageKeyDAO = MessageKeyDAOImpl.INSTANCE;

        DeviceDAOImpl.INSTANCE.setDatabaseHelper(mHelper);
        deviceDAO = DeviceDAOImpl.INSTANCE;
    }

    public UserDAO getUserDAO() {
        return userDAO;
    }

    public ChatDAO getChatDAO() {
        return chatDAO;
    }

    public MessageDAO getMessageDAO() {
        return messageDAO;
    }

    public MessageKeyDAO getMessageKeyDAO() {
        return messageKeyDAO;
    }

    public DeviceDAO getDeviceDAO() {
        return deviceDAO;
    }

    public long getUserId() {
        if (-1 == mUserId) {
            mUserId = getSharedPreferences().getLong(AbstractYasmeActivity.USER_ID, -1);
        }
        return mUserId;
    }

    public void setUserId(long mUserId) {
        this.mUserId = mUserId;
        SharedPreferences.Editor editor = getSharedPreferences().edit();
        editor.putLong(AbstractYasmeActivity.USER_ID, mUserId);
        editor.apply();
    }

    public long getDeviceId() {
        if (-1 == mDeviceId) {
            mDeviceId = getSharedPreferences().getLong(AbstractYasmeActivity.DEVICE_ID, -1);
        }
        return mDeviceId;
    }

    public void setDeviceId(long mDeviceId) {
        this.mDeviceId = mDeviceId;
        SharedPreferences.Editor editor = getSharedPreferences().edit();
        editor.putLong(AbstractYasmeActivity.DEVICE_ID, mDeviceId);
        editor.apply();
    }

    public String getAccessToken() {
        if (null == mAccessToken) {
            mAccessToken = getSharedPreferences().getString(AbstractYasmeActivity.ACCESSTOKEN, null);
        }
        return mAccessToken;
    }

    public void setAccessToken(String accessToken) {
        this.mAccessToken = accessToken;
        SharedPreferences.Editor editor = getSharedPreferences().edit();
        editor.putString(AbstractYasmeActivity.ACCESSTOKEN, mAccessToken);
        editor.commit();
    }

    public long getServerInfoUpdateTime() {
        if (-1 == serverInfoUpdateTime) {
            serverInfoUpdateTime = getSharedPreferences().getLong(AbstractYasmeActivity.SERVERINFOUPDATETIME, -1);
        }
        return serverInfoUpdateTime;
    }

    public void setServerInfoUpdateTime() {
        this.serverInfoUpdateTime = System.currentTimeMillis();
        SharedPreferences.Editor editor = getSharedPreferences().edit();
        editor.putLong(AbstractYasmeActivity.SERVERINFOUPDATETIME, serverInfoUpdateTime);
        editor.commit();
    }

    public ServerInfo getServerInfo() {
        return serverInfo;
    }

    public void setServerInfo(ServerInfo serverInfo) {
        this.serverInfo = serverInfo;
    }

    public String getUserEmail() {
        if (null == mUserEmail || "" == mUserEmail) {
            mUserEmail = getSharedPreferences().getString(AbstractYasmeActivity.USER_MAIL, null);
        }
        return mUserEmail;
    }

    public void setUserEmail(String mUserEmail) {
        this.mUserEmail = mUserEmail;
        SharedPreferences.Editor editor = getSharedPreferences().edit();
        editor.putString(AbstractYasmeActivity.USER_MAIL, mUserEmail);
        editor.commit();
    }

    public NewMessageNotificationManager getNotifier() {
        if (notifier == null) {
            notifier = new NewMessageNotificationManager();
        }
        return notifier;
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/controller/ObservableRegistry.java
public class ObservableRegistry {

    private static ArrayList<ObservableRegistryEntry> entries = new ArrayList<ObservableRegistryEntry>();

    public static <T extends NotifiableFragment<P>, P> FragmentObservable<T, P> getObservable(Class fragmentClass) {
        for (ObservableRegistryEntry entry : entries) {
            if (entry.check(fragmentClass)) {
                Log.d("ObserverRegistry","Returned existing observable");
                return (FragmentObservable<T,P>) entry.getObs(); // no idea how to solve this... 
            }
        }

        FragmentObservable<T, P> res = new FragmentObservable<T, P>();
        Log.d("ObserverRegistry","Created new observable");
        entries.add(new ObservableRegistryEntry<P>(res,fragmentClass));
        return res;
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/controller/Log.java
public class Log {
    static final boolean LOG_I = BuildConfig.DEBUG;
    static final boolean LOG_E = BuildConfig.DEBUG;
    static final boolean LOG_D = BuildConfig.DEBUG;
    static final boolean LOG_V = BuildConfig.DEBUG;
    static final boolean LOG_W = BuildConfig.DEBUG;

    public static void i(String tag, String string) {
        if (LOG_I) android.util.Log.i(tag, string);
    }
    public static void e(String tag, String string) {
        if (LOG_E) android.util.Log.e(tag, string);
    }
    public static void d(String tag, String string) {
        if (LOG_D) android.util.Log.d(tag, string);
    }
    public static void v(String tag, String string) {
        if (LOG_V) android.util.Log.v(tag, string);
    }
    public static void w(String tag, String string) {
        if (LOG_W) android.util.Log.w(tag, string);
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/asyncTasks/server/ChangeChatProperties.java
public class ChangeChatProperties extends AsyncTask<String, Void, Boolean> {
    private Chat chat;
    private Class classToNotify;

    public ChangeChatProperties(Chat chat, Class classToNotify) {
        this.chat = chat;
        this.classToNotify = classToNotify;
    }


    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        SpinnerObservable.getInstance().registerBackgroundTask(this);
    }

    /**
     * @return Returns true if it was successful, otherwise false
     */
    @Override
    protected Boolean doInBackground(String... params) {
        try {
            ChatTask.getInstance().updateChat(chat);
        } catch (RestServiceException e) {
            Log.e(this.getClass().getSimpleName(), e.getMessage());
            return false;
        }
        DatabaseManager.INSTANCE.getChatDAO().update(chat);
        return true;
    }

    /**
     *
     */
    protected void onPostExecute(final Boolean success) {
        SpinnerObservable.getInstance().removeBackgroundTask(this);
        if (success) {
            ObservableRegistry.getObservable(classToNotify).notifyFragments(chat);
            Toaster.getInstance().toast(R.string.change_successful, Toast.LENGTH_LONG);
        } else {
            Toaster.getInstance().toast(R.string.change_not_successful, Toast.LENGTH_LONG);
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/ui/activities/ChatSettingsActivity.java
public class ChatSettingsActivity extends AbstractYasmeActivity {
    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link android.support.v13.app.FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v13.app.FragmentStatePagerAdapter}.
     */
    public static final String CHAT_ID = "chatId";

    ChatSettingsActivity.SectionsPagerAdapter mSectionsPagerAdapter;
    ViewPager mViewPager;

    private long chatId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //progress bar in actionbar
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

        chatId = getIntent().getLongExtra(CHAT_ID, -1);
        if (chatId <= 0) {
            throw new IllegalArgumentException("chatId <= 0");
        }

        setContentView(R.layout.activity_contact);

        // Set up the action bar.
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        if(mViewPager == null) {
            Log.e(this.getClass().getSimpleName(), "ViewPager ist null");
        }
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        // Create a tab listener that is called when the user changes tabs.
        ActionBar.TabListener tabListener = new ActionBar.TabListener() {
            public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
                // When the tab is selected, switch to the
                // corresponding page in the ViewPager.
                mViewPager.setCurrentItem(tab.getPosition());
            }

            public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
                // hide the given tab
            }

            public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
                // probably ignore this event
            }
        };

        // Add tabs, specifying the tab's text and TabListener
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i))
                    .setTabListener(tabListener));
        }
    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.chat, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int itemId = item.getItemId();
        if (itemId == android.R.id.home) {
            onBackPressed();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


    @Override
    public void onBackPressed() {
        Intent intent = new Intent(this, ChatActivity.class);
        intent.putExtra(AbstractYasmeActivity.CHAT_ID, chatId);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
    }

    /**
     * A {@link android.support.v13.app.FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.

            // It may be a better idea to pass the chat id and retrieve
            Bundle args = new Bundle();
            args.putLong(CHAT_ID, chatId);

            switch (position){
                case 0:
                    ChatSettingsInfo csi = new ChatSettingsInfo();
                    csi.setArguments(args);
                    return csi;
                case 1:
                    ChatSettingsAdd csa = new ChatSettingsAdd();
                    csa.setArguments(args);
                    return csa;
                case 2:
                    ChatSettingsRemove csr = new ChatSettingsRemove();
                    csr.setArguments(args);
                    return csr;
                default:
                    ChatSettingsInfo csid = new ChatSettingsInfo();
                    csid.setArguments(args);
                    return csid;
            }
        }


        @Override
        public int getCount() {
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();
            switch (position) {
                case 0:
                    return getString(R.string.settings_title_tab1).toUpperCase(l);
                case 1:
                    return getString(R.string.settings_title_tab2).toUpperCase(l);
                case 2:
                    return getString(R.string.settings_title_tab3).toUpperCase(l);

            }
            return null;
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/ui/activities/ChatListActivity.java
public class ChatListActivity extends AbstractYasmeActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //progress bar in actionbar
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

        setContentView(R.layout.activity_with_single_fragment);

        if (HttpClient.context == null) {
            HttpClient.context = this.getApplicationContext();
        }

        SharedPreferences devicePrefs = getSharedPreferences(DEVICE_PREFS, MODE_PRIVATE);

        // Make sure that the device has been registered. Otherwise several other tasks will fail
        long deviceId = DatabaseManager.INSTANCE.getDeviceId();
        if (deviceId <= 0) {
            Log.e(this.getClass().getSimpleName(), "Device id should not be <= 0 after login. " +
                    "Looks like the device registration failed but no one was notified about that");
        }

        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .add(R.id.singleFragmentContainer, new ChatListFragment()).commit();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.chatlist, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_add_chat) {
            Intent intent = new Intent(this, InviteToChatActivity.class);
            startActivity(intent);
            return true;
        }
        if (id == R.id.sign_out) {
            new LogoutTask().execute();
        }
        return super.onOptionsItemSelected(item);
    }

    protected void startLoginActivity() {
        //setSignedInFlag(false);
        DatabaseManager.INSTANCE.setAccessToken(null);
        Intent intent = new Intent(this, LoginActivity.class);
        startActivity(intent);
        finish();
    }

    private class LogoutTask extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                AuthorizationTask.getInstance().logoutUser();
            } catch (RestServiceException e) {
                Log.e(this.getClass().getSimpleName(), e.getMessage());
                Log.i(this.getClass().getSimpleName(), "Sign out not succesfull");
                return false;
            }
            return true;
        }

        protected void onPostExecute(Boolean success) {
            if (!success) {
                return;
            }
            startLoginActivity();
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/controller/FragmentObservable.java
public class FragmentObservable<T extends NotifiableFragment<P>,  P> {
    private Set<T> fragments;
    private P buffer;

    public FragmentObservable() {
        fragments = new HashSet<T>();
    }

    public void register(T fragment) {
        fragments.add(fragment);
        if (buffer != null) {
            notifyFragments(buffer);
        }
    }

    public void remove(T fragment) {
        fragments.remove(fragment);
    }

    //addIfNotExists
    public void notifyFragments(P parameter) {
        buffer = parameter;
        for (T fragment : fragments) {
            try {
                Log.d(this.getClass().getSimpleName(), "Notify fragment: " + fragment.getClass().getSimpleName());
                fragment.notifyFragment(parameter);
                buffer = null;
            } catch (Exception e) {
                Log.e(this.getClass().getSimpleName(), "Notify fragment failed: " + fragment.getClass().getSimpleName());
            }
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/asyncTasks/database/GetTask.java
public class GetTask<D extends Object, T extends DAO<D>> extends AsyncTask<Object, Void, Boolean> {

    private T specificDAO;
    private long idToGet;
    private D data;
    private Class classToNotify;

    public GetTask(T specificDAO, long idToGet, Class classToNotify) {
        this.specificDAO = specificDAO;
        this.idToGet = idToGet;
        this.classToNotify = classToNotify;
    }

    @Override
    protected Boolean doInBackground(Object... objects) {
        SpinnerObservable.getInstance().registerBackgroundTask(this);
        return null != (data = specificDAO.get(idToGet));
    }

    @Override
    protected void onPostExecute(Boolean success) {
        SpinnerObservable.getInstance().removeBackgroundTask(this);
        if (success) {
            // Notify
            ObservableRegistry.getObservable(classToNotify).notifyFragments(data);
        } else {
            Log.w(this.getClass().getSimpleName(), "Did not invoke notification as task did not finish successfully.");
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/asyncTasks/database/UpdateTask.java
public class UpdateTask<D extends Object, T extends DAO<D>> extends AsyncTask<Object, Void, Boolean> {

    private T specificDAO;
    private D data;
    private Class classToNotify;

    public UpdateTask(T specificDAO, D data, Class classToNotify) {
        this.specificDAO = specificDAO;
        this.data = data;
        this.classToNotify = classToNotify;
    }

    @Override
    protected Boolean doInBackground(Object... objects) {
        SpinnerObservable.getInstance().registerBackgroundTask(this);
        return null != (data = specificDAO.update(data));
    }

    @Override
    protected void onPostExecute(Boolean success) {
        SpinnerObservable.getInstance().removeBackgroundTask(this);
        if (success) {
            // Notify
            ObservableRegistry.getObservable(classToNotify).notifyFragments(data);
        } else {
            Log.w(this.getClass().getSimpleName(), "Did not invoke notification as task did not finish successfully.");
        }
    }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/controller/Sanitizer.java
public class Sanitizer {
    private static String regex = "A-Za-z0-9 ";

    public static String sanitize(String input) {
        // Replace all non-alphanumerical and non-whitespace characters
        return input.replaceAll("[^"+regex+"]","");
    }

    public static String sanitize(String input, String extra) {
        return input.replaceAll("[^"+regex+extra+"]","");
    }

    public String getRegex() { return this.regex; }
}
yasme/src/main/java/de/fau/cs/mad/yasme/android/entities/User.java
@JsonIgnoreProperties(ignoreUnknown = true)
@DatabaseTable(tableName = DatabaseConstants.USER_TABLE)
public class User implements Serializable {

    @DatabaseField(columnName = DatabaseConstants.USER_ID, id = true)
    private long id;

    @DatabaseField(columnName = DatabaseConstants.USER_NAME)
    private String name;

    //@DatabaseField(columnName = DatabaseConstants.USER_EMAIL)
    private String email;

    private String pw;

    @JsonIgnore
    private List<Device> devices;   // Just for convenience

    @DatabaseField(columnName = DatabaseConstants.USER_LAST_MODIFIED)
    private Date lastModified;

    @DatabaseField(columnName = DatabaseConstants.USER_CREATED)
    private Date created;

    @JsonIgnore
    @DatabaseField(columnName = DatabaseConstants.USER_PICTURE)
    private String profilePicture;


    @JsonIgnore
    @DatabaseField(columnName = DatabaseConstants.CONTACT)
    private int contactFlag = 0;


    public User(String pw, String name, String email) {
        this.pw = pw;
        this.name = name;
        this.email = email;
    }

    public User(String email, String pw) {
        this.email = email;
        this.pw = pw;
    }

    public User(String name, long id) {
        this.name = name;
        this.id = id;
    }

    public User(long id) {
        this.id = id;
    }

    public User(String name, String email, long id) {
        this.name = name;
        this.email = email;
        this.id = id;
    }

    public User() {
        // ORMLite needs a no-arg constructor
    }

    /*
     * Getters
     */

    @JsonIgnoreProperties({"id", "user", "publicKey", "product", "lastModified"})
    public List<Device> getDevices() {
        return devices;
    }

    public String getEmail() {
        return email;
    }

    public String getName() {
        return name;
    }

    public String getPw() {
        return pw;
    }

    public long getId() {
        return id;
    }

    public Date getLastModified() {
        return lastModified;
    }

    public Date getCreated() {
        return created;
    }

    public String getProfilePicture() {
        return profilePicture;
    }

    /*
     * Setters
     */

    public void setDevices(List<Device> devices) {
        this.devices = devices;
    }

    public void setPw(String pw) {
        this.pw = pw;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(long id) {
        this.id = id;
    }

    public void setLastModified(Date lastModified) {
        this.lastModified = lastModified;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public void setProfilePicture(String profilePicture) {
        this.profilePicture = profilePicture;
    }

    @JsonIgnore
    public void addToContacts() {
        contactFlag = 1;
    }

    @JsonIgnore
    public void removeFromContacts() {
        contactFlag = 0;
    }

    @JsonIgnore
    public boolean isContact() {
        return contactFlag == 1;
    }

}
yasme/src/main/java/de/fau/cs/mad/yasme/android/ui/AbstractYasmeActivity.java
public abstract class AbstractYasmeActivity extends Activity implements Toastable {
    public final static String USER_ID = "de.fau.cs.mad.yasme.android.USER_ID";
    public final static String USER_NAME = "de.fau.cs.mad.yasme.android.USER_NAME";
    public final static String USER_MAIL = "de.fau.cs.mad.yasme.android.USER_MAIL";
    public final static String USER_PW = "de.fau.cs.mad.yasme.android.USER_PW";
    public final static String DEVICE_ID = "de.fau.cs.mad.yasme.android.DEVICE_ID";
    public final static String PROFILE_PICTURE = "de.fau.cs.mad.yasme.android.PROFILE_PICTURE";

    public final static String CHAT_ID = "de.fau.cs.mad.yasme.android.CHAT_ID";
    public final static String LAST_MESSAGE_ID = "de.fau.cs.mad.yasme.android.LAST_MESSAGE_ID";

    public final static String ACCESSTOKEN = "de.fau.cs.mad.yasme.android.ACCESSTOKEN";
    public final static String SIGN_IN = "de.fau.cs.mad.yasme.android.SIGN_IN";

    public final static String SERVERINFOUPDATETIME = "de.fau.cs.mad.yasme.android.SERVERINFOUPDATETIME";
    public final static String SERVERMESSAGE = "de.fau.cs.mad.yasme.android.SERVERMESSAGE";

    public final static String STORAGE_PREFS = "de.fau.cs.mad.yasme.android.STORAGE_PREFS";
    public final static String SETTINGS_PREFS = "de.fau.cs.mad.yasme.android.SETTINGS_PREFS";
    public final static String DEVICE_PREFS = "de.fau.cs.mad.yasme.android.DEVICE_PREFS";
    public final static String PUSH_PREFS = "de.fau.cs.mad.yasme.android.PUSH_PREFS";

    public final static String NOTIFICATION_VIBRATE = "de.fau.cs.mad.yasme.android.NOTIFICATION_VIBRATE";
    public final static String NOTIFICATION_SOUND = "de.fau.cs.mad.yasme.android.NOTIFICATION_SOUND";


    //GCM Properties
    public static final String PROPERTY_REG_ID = "registration_id";
    public static final String PROPERTY_APP_VERSION = "appVersion";
    public static final String SENDER_ID = "688782154540"; //"104759172131";
    public static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
    public static final String TAG = "YasmeGCM";

    protected User selfUser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!ConnectionTask.isInitialized()) {
            String server = getResources().getString(R.string.server_host);
            if (BuildConfig.DEBUG) {
                server = getResources().getString(R.string.server_host_debug);
            }
            Log.d(getClass().getSimpleName(), "YASME-Server: " + server);
            ConnectionTask.initParams(getResources().getString(R.string.server_scheme),
                    server,
                    getResources().getString(R.string.server_port), getResources().getString(R.string.language), getVersion());
        }

        SharedPreferences storage = getSharedPreferences(STORAGE_PREFS, MODE_PRIVATE);
        SharedPreferences settings = getSharedPreferences(SETTINGS_PREFS, MODE_PRIVATE);
        Long userId = storage.getLong(USER_ID, 0);
        String userName = storage.getString(USER_NAME, "");
        String userMail = storage.getString(USER_MAIL, "");
        String userPw = storage.getString(USER_PW, "password");

        if(selfUser==null) {
            selfUser = new User();
        }
        selfUser.setId(userId);
        selfUser.setName(userName);
        selfUser.setEmail(userMail);
        selfUser.setPw(userPw);


        //Initialize databaseManager (once in application)
        if (!DatabaseManager.INSTANCE.isInitialized()) {
            DatabaseManager.INSTANCE.init(this, storage, settings, userId);
        }
        //Init QR-Code
        QR.init(false);

        String accessToken = DatabaseManager.INSTANCE.getAccessToken();
        if ((accessToken == null || accessToken.length() <= 0) && !this.getClass().equals(LoginActivity.class)) {
            Log.i(this.getClass().getSimpleName(), "Not logged in, starting login activity");
            Intent intent = new Intent(this, LoginActivity.class);
            startActivity(intent);
            finish();
            return;
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        Toaster.getInstance().register(this);
        stopSpinning();
        SpinnerObservable.getInstance().registerActivity(this);
    }

    @Override
    public void onResume() {
        super.onResume();
        String accessToken = DatabaseManager.INSTANCE.getAccessToken();
        if ((accessToken == null || accessToken.length() <= 0) && !this.getClass().equals(LoginActivity.class)) {
            Log.i(this.getClass().getSimpleName(), "Not logged in, starting login activity");
            Intent intent = new Intent(this, LoginActivity.class);
            startActivity(intent);
            finish();
            return;
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        Toaster.getInstance().remove(this);
        SpinnerObservable.getInstance().removeActivity(this);
    }

    public void setActionBarTitle(String title) {
        getActionBar().setTitle(title);
    }

    public void setActionBarTitle(String title, String subtitle) {
        getActionBar().setTitle(title);
        getActionBar().setSubtitle(subtitle);
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        Intent intent;
        int itemId = item.getItemId();
        switch (itemId) {
            case android.R.id.home:
                if (NavUtils.getParentActivityName(this) != null) {
                    NavUtils.navigateUpFromSameTask(this);
                }
                return true;
            case R.id.action_settings:
                intent = new Intent(this, SettingsActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
                return true;
            case R.id.action_chats:
                intent = new Intent(this, ChatListActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
                return true;
            case R.id.action_add_chat:
                intent = new Intent(this, InviteToChatActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                startActivity(intent);
                return true;
            case R.id.action_contacts:
                intent = new Intent(this, ContactActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);

        }
    }

    public String getSelfName() {

        if(selfUser==null) {
            SharedPreferences storage = getSharedPreferences(STORAGE_PREFS, MODE_PRIVATE);
            Long userId = storage.getLong(USER_ID, 0);
            String userName = storage.getString(USER_NAME, "");
            String userMail = storage.getString(USER_MAIL, "");
            String userPw = storage.getString(USER_PW, "password");

            selfUser = new User();
            selfUser.setId(userId);
            selfUser.setName(userName);
            selfUser.setEmail(userMail);
            selfUser.setPw(userPw);
        }
        if (selfUser.getName().isEmpty()) {
            String name = getSharedPreferences(STORAGE_PREFS, MODE_PRIVATE).getString(USER_NAME, "");
            selfUser.setName(name);
        }
        return selfUser.getName();
    }

    public User getSelfUser() {
        return selfUser;
    }

    public String getUserMail() {
        if (selfUser == null || selfUser.getEmail().isEmpty()) {
            String mail = getSharedPreferences(STORAGE_PREFS, MODE_PRIVATE).getString(USER_MAIL, "");
            selfUser.setEmail(mail);
        }
        return selfUser.getEmail();
    }

    public long getUserId() {
        return selfUser.getId();
    }

    public String getOwnProfilePicture() {
        String path = selfUser.getProfilePicture();
        if (path == null || path.isEmpty()) {
            path = getSharedPreferences(STORAGE_PREFS, MODE_PRIVATE).getString(PROFILE_PICTURE, null);
        }
        return path;
    }

    public void setOwnProfilePicture(String ownProfilePicture) {
        selfUser.setProfilePicture(ownProfilePicture);
        SharedPreferences.Editor editor = getSharedPreferences(STORAGE_PREFS, MODE_PRIVATE).edit();
        editor.putString(AbstractYasmeActivity.PROFILE_PICTURE, ownProfilePicture);
        editor.commit();
    }

    public String getAccessToken() {
        return DatabaseManager.INSTANCE.getAccessToken();
    }

    public void toast(final int messageId, final int duration) {
        String text = getApplicationContext().getResources().getString(messageId);
        toast(text, duration, -1);
    }

    public void toast(final String text, final int duration) {
        toast(text, duration, -1);
    }

    public void toast(final String text, final int duration, final int gravity) {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast toast = Toast.makeText(getApplicationContext(), text, duration);
                if (-1 != gravity) {
                    toast.setGravity(gravity, 0, 0);
                }
                // otherwise use default position
                Log.d(getClass().getSimpleName(), "Toast: " + text);
                toast.show();
            }
        });
    }

    public void startSpinning() {
        runOnUiThread(new Runnable() {
            public void run() {
                setProgressBarIndeterminateVisibility(true);
            }
        });
    }

    public void stopSpinning() {
        runOnUiThread(new Runnable() {
            public void run() {
                setProgressBarIndeterminateVisibility(false);
            }
        });
    }

    public int getVersion() {
        try {
            return getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
        } catch (Exception e) {
            Log.e(this.getClass().getSimpleName(), e.getMessage());
            return 0;
        }
    }

}


Question: package de.fau.cs.mad.yasme.android.ui.fragments;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import de.fau.cs.mad.yasme.android.EditTextWithX;
import de.fau.cs.mad.yasme.android.R;
import de.fau.cs.mad.yasme.android.asyncTasks.database.GetTask;
import de.fau.cs.mad.yasme.android.asyncTasks.database.UpdateTask;
import de.fau.cs.mad.yasme.android.asyncTasks.server.ChangeChatProperties;
import de.fau.cs.mad.yasme.android.asyncTasks.server.ChangeOwnerAndLeaveTask;
import de.fau.cs.mad.yasme.android.asyncTasks.server.LeaveChatTask;
import de.fau.cs.mad.yasme.android.controller.FragmentObservable;
import de.fau.cs.mad.yasme.android.controller.Log;
import de.fau.cs.mad.yasme.android.controller.NotifiableFragment;
import de.fau.cs.mad.yasme.android.controller.ObservableRegistry;
import de.fau.cs.mad.yasme.android.controller.Sanitizer;
import de.fau.cs.mad.yasme.android.entities.Chat;
import de.fau.cs.mad.yasme.android.entities.User;
import de.fau.cs.mad.yasme.android.storage.DatabaseManager;
import de.fau.cs.mad.yasme.android.storage.dao.ChatDAO;
import de.fau.cs.mad.yasme.android.ui.AbstractYasmeActivity;
import de.fau.cs.mad.yasme.android.ui.UserAdapter;
import de.fau.cs.mad.yasme.android.ui.activities.ChatListActivity;
import de.fau.cs.mad.yasme.android.ui.activities.ChatSettingsActivity;




/**
 * Created by Robert Meissner <robert.meissner@studium.fau.de> on 03.08.14.
 */
public class ChatSettingsInfo extends Fragment implements NotifiableFragment<Chat> {
    private List<User> users;
    protected UserAdapter mAdapter = null;
    private View chatInfo;
    private Chat chat;
    private Button changeName, changeStatus, leaveChat, changeOwner, resetName, resetStatus;

    public ChatSettingsInfo() {
    }

    @Override
    public void onStart() {
        super.onStart();
Answer:         Log.d(this.getClass().getSimpleName(), "onStart");