/*
* Kontalk Android client
* Copyright (C) 2017 Kontalk Devteam <devteam@kontalk.org>
* 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.kontalk.message;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import android.content.Context;
import android.database.Cursor;
import org.kontalk.R;
import org.kontalk.client.GroupExtension;
/**
* Component for group commands.
* @author Daniele Ricci
*/
public class GroupCommandComponent extends MessageComponent<GroupExtension> {
/** MIME type for command messages. */
public static final String MIME_TYPE = "application/x-kontalk-group";
// create group
public static final String COMMAND_CREATE = "create";
// leave group
public static final String COMMAND_PART = "part";
// set subject
public static final String COMMAND_SUBJECT = "subject";
// add members
public static final String COMMAND_ADD = "add";
// remove members
public static final String COMMAND_REMOVE = "remove";
private final String mFrom;
private final String mOwnJid;
public GroupCommandComponent(GroupExtension content, String from, String ownJid) {
super(content, 0, false, 0);
mFrom = from;
mOwnJid = ownJid;
}
public String getFrom() {
return mFrom;
}
public static boolean supportsMimeType(String mime) {
return MIME_TYPE.equalsIgnoreCase(mime);
}
public boolean isCreateCommand() {
return mContent.getType() == GroupExtension.Type.CREATE;
}
public boolean isPartCommand() {
return mContent.getType() == GroupExtension.Type.PART;
}
public boolean isAddOrRemoveCommand() {
return mContent.getType() == GroupExtension.Type.SET &&
mContent.getMembers().size() > 0;
}
public boolean isSetSubjectCommand() {
return mContent.getType() == GroupExtension.Type.SET;
}
public String[] getCreateMembers() {
if (!isCreateCommand())
throw new UnsupportedOperationException("Not a create command");
return flattenOperationMembers(GroupExtension.Member.Operation.NONE, true);
}
public String[] getExistingMembers() {
return flattenOperationMembers(GroupExtension.Member.Operation.NONE, true);
}
public String[] getAddedMembers() {
if (!isAddOrRemoveCommand())
throw new UnsupportedOperationException("Not an add or remove command");
return flattenOperationMembers(GroupExtension.Member.Operation.ADD, false);
}
public String[] getRemovedMembers() {
if (!isAddOrRemoveCommand())
throw new UnsupportedOperationException("Not an add or remove command");
return flattenOperationMembers(GroupExtension.Member.Operation.REMOVE, false);
}
private String[] flattenOperationMembers(GroupExtension.Member.Operation operation, boolean includeOwner) {
List<GroupExtension.Member> members = mContent.getMembers();
Set<String> output = new HashSet<>();
if (includeOwner)
output.add(mContent.getOwner());
for (int i = 0; i < members.size(); i++) {
GroupExtension.Member user = members.get(i);
// exclude own JID from the list
if (user.operation == operation)
output.add(user.jid);
}
return output.toArray(new String[output.size()]);
}
/** Returns the text to be used as the body content in the database. */
public String getTextContent() {
if (isCreateCommand())
return getCreateBodyContent(getCreateMembers());
else if (isPartCommand())
return COMMAND_PART;
else if (isAddOrRemoveCommand()) {
return getAddMembersBodyContent(getAddedMembers()) +
getRemoveMembersBodyContent(getRemovedMembers());
}
else if (isSetSubjectCommand()) {
return getSetSubjectCommandBodyContent(mContent.getSubject());
}
// TODO
throw new UnsupportedOperationException("Unsupported group command");
}
public static String getCreateBodyContent(String[] members) {
StringBuilder out = new StringBuilder(COMMAND_CREATE).append(":");
for (String m : members)
out.append(m).append(";");
return out.toString();
}
public static String getSetSubjectCommandBodyContent(String subject) {
return COMMAND_SUBJECT + ":" + subject;
}
public static String getLeaveCommandBodyContent() {
return COMMAND_PART;
}
public static String getAddMembersBodyContent(String[] members) {
String prefix = GroupCommandComponent.COMMAND_ADD + ":";
StringBuilder out = new StringBuilder();
for (String m : members)
out.append(prefix).append(m).append(";");
return out.toString();
}
public static String getRemoveMembersBodyContent(String[] members) {
String prefix = GroupCommandComponent.COMMAND_REMOVE + ":";
StringBuilder out = new StringBuilder();
for (String m : members)
out.append(prefix).append(m).append(";");
return out.toString();
}
public static String[] getCreateCommandMembers(String body) {
String prefix = GroupCommandComponent.COMMAND_CREATE + ":";
if (body.startsWith(prefix)) {
String[] params = body.substring(prefix.length()).split(";");
Set<String> members = new HashSet<>();
for (String m : params) {
if (m.length() > 0)
members.add(m);
}
return members.toArray(new String[members.size()]);
}
return null;
}
private static String[] getPrefixCommandMembers(String body, String prefix) {
String[] cmdParams = body.split(";");
Set<String> members = new HashSet<>();
for (String param : cmdParams) {
if (param.startsWith(prefix))
members.add(param.substring(prefix.length()));
}
return (members.size() > 0) ?
members.toArray(new String[members.size()]) : null;
}
public static String[] getAddCommandMembers(String body) {
return getPrefixCommandMembers(body, "add:");
}
public static String[] getRemoveCommandMembers(String body) {
return getPrefixCommandMembers(body, "remove:");
}
public static String getSubjectCommand(String body) {
String prefix = GroupCommandComponent.COMMAND_SUBJECT + ":";
if (body.startsWith(prefix)) {
return body.substring(prefix.length());
}
return null;
}
public static String getTextContent(Context context, String bodyContent, boolean incoming) {
if (bodyContent.startsWith(COMMAND_CREATE)) {
return context.getString(R.string.group_command_text_create);
}
else if (bodyContent.startsWith(COMMAND_PART)) {
return context.getString(incoming ?
R.string.group_command_text_part : R.string.group_command_text_part_self);
}
else if (bodyContent.startsWith(COMMAND_SUBJECT)) {
return context.getString(R.string.group_command_text_subject);
}
else if (bodyContent.contains(COMMAND_ADD) || bodyContent.contains(COMMAND_REMOVE)) {
return context.getString(R.string.group_command_text_add_remove);
}
// this shouldn't happen
throw new UnsupportedOperationException("Unknown group command: " + bodyContent);
}
public static List<GroupExtension.Member> membersFromJIDs(String[] members) {
return membersFromJIDs(members, null, null);
}
public static List<GroupExtension.Member> membersFromJIDs(String[] members, String[] added, String[] removed) {
List<GroupExtension.Member> list = new ArrayList<>(
(members != null ? members.length : 0) +
(added != null ? added.length : 0) +
(removed != null ? removed.length : 0));
if (members != null) {
for (String m : members)
list.add(new GroupExtension.Member(m, GroupExtension.Member.Operation.NONE));
}
if (added != null) {
for (String m : added)
list.add(new GroupExtension.Member(m, GroupExtension.Member.Operation.ADD));
}
if (removed != null) {
for (String m : removed)
list.add(new GroupExtension.Member(m, GroupExtension.Member.Operation.REMOVE));
}
return list;
}
/** Returns true if the given cursor is a group command message. */
public static boolean isCursor(Cursor cursor) {
return MIME_TYPE.equals(cursor.getString(CompositeMessage.COLUMN_BODY_MIME));
}
}