package org.buddycloud.channelserver.channel.node.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.buddycloud.channelserver.channel.ChannelManager;
import org.buddycloud.channelserver.channel.node.configuration.field.AccessModel;
import org.buddycloud.channelserver.channel.node.configuration.field.Affiliation;
import org.buddycloud.channelserver.channel.node.configuration.field.ChannelType;
import org.buddycloud.channelserver.channel.node.configuration.field.ConfigurationFieldException;
import org.buddycloud.channelserver.channel.node.configuration.field.ContentType;
import org.buddycloud.channelserver.channel.node.configuration.field.CreationDate;
import org.buddycloud.channelserver.channel.node.configuration.field.Creator;
import org.buddycloud.channelserver.channel.node.configuration.field.Factory;
import org.buddycloud.channelserver.channel.node.configuration.field.Field;
import org.buddycloud.channelserver.channel.node.configuration.field.LastUpdatedDate;
import org.buddycloud.channelserver.channel.node.configuration.field.NodeDescription;
import org.buddycloud.channelserver.channel.node.configuration.field.NodeTitle;
import org.buddycloud.channelserver.db.exception.NodeStoreException;
import org.dom4j.Element;
import org.xmpp.forms.DataForm;
import org.xmpp.forms.FormField;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Message;
public class Helper {
private HashMap<String, Field> elements;
private Factory fieldFactory;
private ChannelManager channelManager;
public static final String FORM_TYPE = "http://jabber.org/protocol/pubsub#node_config";
private static final String ELEMENT_NOT_FOUND = "Required XMPP element not found";
private static final Logger LOGGER = Logger.getLogger(Helper.class);
private static final String NODE_NOT_SET = "node-not-set";
private ArrayList<String> requiredFields = new ArrayList<String>();
private HashMap<String, String> existingConfiguration;
private String node;
public Helper(ChannelManager channelManager) {
setupRequiredFields();
this.channelManager = channelManager;
}
public void setNode(String node) {
this.node = node;
}
private String getNode() {
if ((null == node) || (0 == node.length())) {
throw new NodeConfigurationException(NODE_NOT_SET);
}
return this.node;
}
private void setupRequiredFields() {
requiredFields.add(NodeTitle.FIELD_NAME);
requiredFields.add(NodeDescription.FIELD_NAME);
requiredFields.add(AccessModel.FIELD_NAME);
requiredFields.add(Creator.FIELD_NAME);
requiredFields.add(Affiliation.FIELD_NAME);
requiredFields.add(ChannelType.FIELD_NAME);
requiredFields.add(ContentType.FIELD_NAME);
requiredFields.add(CreationDate.FIELD_NAME);
requiredFields.add(LastUpdatedDate.FIELD_NAME);
}
public void parse(IQ request) throws NodeConfigurationException {
try {
parseConfiguration(getConfigurationValues(request));
} catch (NullPointerException e) {
LOGGER.debug(e);
throw new NodeConfigurationException(ELEMENT_NOT_FOUND);
} catch (ConfigurationFieldException e) {
LOGGER.debug(e);
throw new NodeConfigurationException();
}
}
public void parseEventUpdate(Message request) throws NodeConfigurationException {
try {
parseConfiguration(getConfigurationValuesFromEvent(request));
} catch (NullPointerException e) {
LOGGER.debug(e);
throw new NodeConfigurationException(ELEMENT_NOT_FOUND);
} catch (ConfigurationFieldException e) {
LOGGER.debug(e);
throw new NodeConfigurationException();
}
}
private List<FormField> getConfigurationValuesFromEvent(Message request) {
Element element = request.getElement().element("event").element("configuration").element("x");
DataForm dataForm = new DataForm(element);
List<FormField> fields = dataForm.getFields();
return fields;
}
public void parseDiscoInfo(IQ request) throws NodeConfigurationException {
try {
parseConfiguration(getConfigurationValuesFromDisco(request));
} catch (NullPointerException e) {
LOGGER.debug(e);
throw new NodeConfigurationException(ELEMENT_NOT_FOUND);
} catch (ConfigurationFieldException e) {
LOGGER.debug(e);
throw new NodeConfigurationException();
}
}
private List<FormField> getConfigurationValuesFromDisco(IQ request) {
Element element = request.getElement().element("query").element("x");
DataForm dataForm = new DataForm(element);
List<FormField> fields = dataForm.getFields();
return fields;
}
private List<FormField> getConfigurationValues(IQ request) {
Element element = request.getElement().element("pubsub").element("configure").element("x");
DataForm dataForm = new DataForm(element);
List<FormField> fields = dataForm.getFields();
return fields;
}
private void parseConfiguration(List<FormField> configurationValues) {
elements = new HashMap<String, Field>();
if (configurationValues.isEmpty()) {
return;
}
for (FormField configurationValue : configurationValues) {
Field field = getFieldFactory().create(configurationValue.getVariable(), configurationValue.getFirstValue());
elements.put(field.getName(), field);
}
}
private Factory getFieldFactory() {
if (fieldFactory == null) {
fieldFactory = new Factory();
}
return fieldFactory;
}
public void setFieldFactory(Factory factory) {
fieldFactory = factory;
}
public boolean isValid() {
for (Entry<String, Field> element : elements.entrySet()) {
if (!element.getValue().isValid()) {
LOGGER.debug("Configuration field " + element.getValue().getName() + " is not valid with value " + element.getValue().getValue());
return false;
}
}
return true;
}
public HashMap<String, String> getValues() throws NodeStoreException {
if (null == node) {
existingConfiguration = new HashMap<String, String>();
} else {
existingConfiguration = (HashMap<String, String>) channelManager.getNodeConf(getNode());
}
HashMap<String, String> data = new HashMap<String, String>();
for (Entry<String, Field> element : elements.entrySet()) {
String value = element.getValue().getValue();
String key = element.getValue().getName();
LOGGER.trace("For '" + key + "' we are storing value '" + value + "'");
data.put(key, value);
}
addRequiredFields(data);
cleanData(data);
return data;
}
private void addRequiredFields(HashMap<String, String> data) {
for (String field : requiredFields) {
if (!data.containsKey(field)) {
if (existingConfiguration.containsKey(field)) {
data.put(field, existingConfiguration.get(field));
} else if (elements.containsKey(field)) {
data.put(field, elements.get(field).getValue());
}
}
}
}
private void cleanData(HashMap<String, String> data) {
preventOverwrite(data, ChannelType.FIELD_NAME);
preventOverwrite(data, CreationDate.FIELD_NAME);
preventOverwrite(data, Creator.FIELD_NAME);
preventOverwrite(data, ContentType.FIELD_NAME);
ensurePresent(data, NodeTitle.FIELD_NAME);
ensurePresent(data, NodeDescription.FIELD_NAME);
ensurePresent(data, AccessModel.FIELD_NAME);
ensurePresent(data, Affiliation.FIELD_NAME);
setLastUpdatedDate(data);
}
private void setLastUpdatedDate(HashMap<String, String> data) {
data.remove(LastUpdatedDate.FIELD_NAME);
String lastUpdated = getFieldFactory().create(LastUpdatedDate.FIELD_NAME, "").getValue();
data.put(LastUpdatedDate.FIELD_NAME, lastUpdated);
}
private void ensurePresent(HashMap<String, String> data, String fieldName) {
if (data.containsKey(fieldName)) {
return;
}
if (!existingConfiguration.containsKey(fieldName)) {
return;
}
data.put(fieldName, existingConfiguration.get(fieldName));
}
private void preventOverwrite(HashMap<String, String> data, String fieldName) {
if (!data.containsKey(fieldName) || !existingConfiguration.containsKey(fieldName)) {
return;
}
data.remove(fieldName);
data.put(fieldName, existingConfiguration.get(fieldName));
}
}