<commit_before>/*
 *  Copyright 2010 Vodafone Group Services Ltd.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *    
 */
package org.onesocialweb.gwt.service.imp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.onesocialweb.gwt.model.GwtActivityDomReader;
import org.onesocialweb.gwt.model.GwtActivityDomWriter;
import org.onesocialweb.gwt.model.GwtRelationDomReader;
import org.onesocialweb.gwt.model.GwtRelationDomWriter;
import org.onesocialweb.gwt.model.GwtVCard4DomReader;
import org.onesocialweb.gwt.model.GwtVCard4DomWriter;
import org.onesocialweb.gwt.model.vcard4.GwtProfileFactory;
import org.onesocialweb.gwt.service.OswService;
import org.onesocialweb.gwt.service.RequestCallback;
import org.onesocialweb.gwt.service.Roster;
import org.onesocialweb.gwt.service.RosterItem;
import org.onesocialweb.gwt.service.Stream;
import org.onesocialweb.gwt.service.UpdateCallback;
import org.onesocialweb.gwt.service.UploadStatus;
import org.onesocialweb.gwt.service.RosterItem.Presence;
import org.onesocialweb.gwt.xml.DocumentAdapter;
import org.onesocialweb.gwt.xml.ElementAdapter;
import org.onesocialweb.model.acl.AclFactory;
import org.onesocialweb.model.acl.DefaultAclFactory;
import org.onesocialweb.model.activity.ActivityEntry;
import org.onesocialweb.model.activity.ActivityFactory;
import org.onesocialweb.model.activity.DefaultActivityFactory;
import org.onesocialweb.model.atom.AtomFactory;
import org.onesocialweb.model.atom.DefaultAtomFactory;
import org.onesocialweb.model.relation.DefaultRelationFactory;
import org.onesocialweb.model.relation.Relation;
import org.onesocialweb.model.relation.RelationFactory;
import org.onesocialweb.model.vcard4.Profile;
import org.onesocialweb.model.vcard4.VCard4Factory;
import org.onesocialweb.xml.dom.ActivityDomReader;
import org.onesocialweb.xml.dom.ActivityDomWriter;
import org.onesocialweb.xml.dom.RelationDomReader;
import org.onesocialweb.xml.dom.RelationDomWriter;
import org.onesocialweb.xml.dom.VCard4DomReader;
import org.onesocialweb.xml.dom.VCard4DomWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.allen_sauer.gwt.log.client.Log;
import com.calclab.emite.core.client.bosh.BoshSettings;
import com.calclab.emite.core.client.bosh.Connection;
import com.calclab.emite.core.client.packet.IPacket;
import com.calclab.emite.core.client.packet.Packet;
import com.calclab.emite.core.client.packet.gwt.GWTPacket;
import com.calclab.emite.core.client.xmpp.session.Session;
import com.calclab.emite.core.client.xmpp.session.Session.State;
import com.calclab.emite.core.client.xmpp.stanzas.IQ;
import com.calclab.emite.core.client.xmpp.stanzas.Message;
import com.calclab.emite.core.client.xmpp.stanzas.XmppURI;
import com.calclab.emite.core.client.xmpp.stanzas.Presence.Show;
import com.calclab.emite.im.client.presence.PresenceManager;
import com.calclab.emite.im.client.presence.PresenceManagerImpl;
import com.calclab.emite.im.client.roster.RosterImpl;
import com.calclab.suco.client.Suco;
import com.calclab.suco.client.events.Listener;
import com.google.gwt.xml.client.XMLParser;

public class GwtOswService implements OswService {

	private static GwtOswService instance;

	private final Session session = Suco.get(Session.class);

	private final ActivityFactory activityFactory = new DefaultActivityFactory();

	private final AclFactory aclFactory = new DefaultAclFactory();

	private final AtomFactory atomFactory = new DefaultAtomFactory();

	private final VCard4Factory profileFactory = new GwtProfileFactory();

	private final RelationFactory relationFactory = new DefaultRelationFactory();

	private final Map<String, Object> cache = new HashMap<String, Object>();

	private final GwtInbox inbox = new GwtInbox();

	private final QueryCache queryCache = new QueryCache();

	private RequestCallback<?> loginCallback;

	private RequestCallback<?> logoutCallback;

	private Map<String, UpdateCallback<UploadStatus>> uploadCallbacks = new HashMap<String, UpdateCallback<UploadStatus>>();

	private String domain;

	private Roster roster;

	private PresenceManager presenceManager;

	public static GwtOswService getInstance() {
		if (instance == null) {
			instance = new GwtOswService();
		}
		return instance;
	}

	@Override
	public AclFactory getAclFactory() {
		return aclFactory;
	}

	@Override
	public ActivityFactory getActivityFactory() {
		return activityFactory;
	}

	@Override
	public AtomFactory getAtomFactory() {
		return atomFactory;
	}

	@Override
	public VCard4Factory getProfileFactory() {
		return profileFactory;
	}

	@Override
	public RelationFactory getRelationFactory() {
		return relationFactory;
	}

	@Override
	public void setup(String httpBase, String hostname, String domain) {
		Suco.get(Connection.class).setSettings(
				new BoshSettings(httpBase, hostname));
		session.onStateChanged(new StateChangedListener());
		session.onMessage(new MessageListener());
		this.domain = domain;
	}

	@Override
	public void login(String username, String password,
			RequestCallback<Object> callback) {
		if (logoutCallback == null && loginCallback == null) {
			loginCallback = callback;
			RosterImpl rosterImpl = new RosterImpl(session);
			roster = new GwtRoster(rosterImpl);
			presenceManager = new PresenceManagerImpl(session, rosterImpl);
			session.login(XmppURI.uri(username + "@" + domain), password);
		}
	}

	@Override
	public void logout(RequestCallback<Object> callback) {
		if (logoutCallback == null && loginCallback == null) {
			logoutCallback = callback;
			session.logout();
		}
	}

	@Override
	public boolean isLoggedIn() {
		return session.isLoggedIn();
	}

	@Override
	public Stream<ActivityEntry> getInbox() {
		return inbox;
	}

	@Override
	public void getProfile(final String jid,
			final RequestCallback<Profile> callback) {
		// Hit the cache
		if (cache.containsKey("profile_" + jid)) {
			Object value = cache.get("profile_" + jid);
			if (value != null && value instanceof Profile) {
				callback.onSuccess((Profile) value);
			} else {
				callback.onFailure();
			}
			return;
		}

		// Check if ongoing query
		if (queryCache.hasQuery("profile_" + jid)) {
			queryCache.addCallback("profile_" + jid, new QueryCallback() {

				@Override
				public void onFailure() {
					callback.onFailure();
				}

				@Override
				public void onResult(Object result) {
					if (result != null && result instanceof Profile) {
						callback.onSuccess((Profile) result);
					} else {
						callback.onFailure();
					}
				}
			});
			return;
		}

		// No cache, new query
		queryCache.addQuery("profile_" + jid);
		IQ iq = new IQ(IQ.Type.get);
		iq.addQuery("http://onesocialweb.org/spec/1.0/vcard4#query");
		iq.setTo(XmppURI.jid(jid));
		session.sendIQ("osw", iq, new Listener<IPacket>() {

			public void onEvent(IPacket packet) {
				// Packet should not be an error
				if (IQ.isSuccess(packet)) {
					// Parse the packet and check if a proper query request
					final IPacket query = packet.getFirstChild("query");
					Profile profile = null;
					if (query != null && query.getChildrenCount() > 0) {
						// Parse the packet and return the profile
						IPacket item = query.getFirstChild("vcard");
						if (item instanceof GWTPacket) {
							GWTPacket i_packet = (GWTPacket) item;
							Element element = new ElementAdapter(i_packet
									.getElement());
							VCard4DomReader reader = new GwtVCard4DomReader();
							profile = reader.readProfile(element);
						}
					}

					if (profile == null) {
						profile = profileFactory.profile();
					}

					cache.put("profile_" + jid, profile);
					queryCache.success("profile_" + jid, profile);
					callback.onSuccess(profile);
					return;
				}

				// If we are here, there was an error
				cache.put("profile_" + jid, null);
				queryCache.failure("profile_" + jid);
				callback.onFailure();
			}
		});
	}

	@Override
	public void setProfile(final Profile profile,
			final RequestCallback<Object> callback) {
		VCard4DomWriter writer = new GwtVCard4DomWriter();
		Document document = new DocumentAdapter(XMLParser.createDocument());
		Element element = writer.toElement(profile, document);
		IQ iq = new IQ(IQ.Type.set);
		IPacket publish = iq.addChild("publish",
				"http://onesocialweb.org/spec/1.0/vcard4#publish");
		((Packet) publish).addChild(new GWTPacket(((ElementAdapter) element)
				.getGwtElement()));
		session.sendIQ("osw", iq, new Listener<IPacket>() {

			public void onEvent(IPacket packet) {
				// Check if no error
				if (IQ.isSuccess(packet)) {
					callback.onSuccess(null);
					cache.put("profile_" + getUserBareJID(), profile);
				} else {
					callback.onFailure();
				}
			}
		});
	}

	@Override
	public Stream<ActivityEntry> getActivities(String jid) {
		// Hit the cache
		if (cache.containsKey("activities_" + jid)) {
			return (GwtActivities) cache.get("activities_" + jid);
		}

		// Create, cache, refresh and return
		GwtActivities activities = new GwtActivities(jid);
		activities.refresh(null);
		cache.put("activities_" + jid, activities);
		return activities;
	}

	@Override
	public void getRelations(final String jid,
			final RequestCallback<List<Relation>> callback) {
		IQ iq = new IQ(IQ.Type.get);
		iq.addQuery("http://onesocialweb.org/protocol/0.1/relations#query");
		iq.setTo(XmppURI.jid(jid));
		session.sendIQ("osw", iq, new Listener<IPacket>() {

			public void onEvent(IPacket packet) {
				// Check if not an error
				if (IQ.isSuccess(packet)) {
					// Parse the packet and check if a proper query request
					final IPacket query = packet.getFirstChild("query");
					final RelationDomReader reader = new GwtRelationDomReader();
					if (query != null && query.getChildrenCount() > 0) {
						// Parse the packet and store the notifications
						List<Relation> relations = new ArrayList<Relation>();
						for (IPacket item : query.getChildren()) {<commit_msg>Always refresh activities, even if from cache<commit_after>/*
 *  Copyright 2010 Vodafone Group Services Ltd.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *    
 */
package org.onesocialweb.gwt.service.imp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.onesocialweb.gwt.model.GwtActivityDomReader;
import org.onesocialweb.gwt.model.GwtActivityDomWriter;
import org.onesocialweb.gwt.model.GwtRelationDomReader;
import org.onesocialweb.gwt.model.GwtRelationDomWriter;
import org.onesocialweb.gwt.model.GwtVCard4DomReader;
import org.onesocialweb.gwt.model.GwtVCard4DomWriter;
import org.onesocialweb.gwt.model.vcard4.GwtProfileFactory;
import org.onesocialweb.gwt.service.OswService;
import org.onesocialweb.gwt.service.RequestCallback;
import org.onesocialweb.gwt.service.Roster;
import org.onesocialweb.gwt.service.RosterItem;
import org.onesocialweb.gwt.service.Stream;
import org.onesocialweb.gwt.service.UpdateCallback;
import org.onesocialweb.gwt.service.UploadStatus;
import org.onesocialweb.gwt.service.RosterItem.Presence;
import org.onesocialweb.gwt.xml.DocumentAdapter;
import org.onesocialweb.gwt.xml.ElementAdapter;
import org.onesocialweb.model.acl.AclFactory;
import org.onesocialweb.model.acl.DefaultAclFactory;
import org.onesocialweb.model.activity.ActivityEntry;
import org.onesocialweb.model.activity.ActivityFactory;
import org.onesocialweb.model.activity.DefaultActivityFactory;
import org.onesocialweb.model.atom.AtomFactory;
import org.onesocialweb.model.atom.DefaultAtomFactory;
import org.onesocialweb.model.relation.DefaultRelationFactory;
import org.onesocialweb.model.relation.Relation;
import org.onesocialweb.model.relation.RelationFactory;
import org.onesocialweb.model.vcard4.Profile;
import org.onesocialweb.model.vcard4.VCard4Factory;
import org.onesocialweb.xml.dom.ActivityDomReader;
import org.onesocialweb.xml.dom.ActivityDomWriter;
import org.onesocialweb.xml.dom.RelationDomReader;
import org.onesocialweb.xml.dom.RelationDomWriter;
import org.onesocialweb.xml.dom.VCard4DomReader;
import org.onesocialweb.xml.dom.VCard4DomWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.allen_sauer.gwt.log.client.Log;
import com.calclab.emite.core.client.bosh.BoshSettings;
import com.calclab.emite.core.client.bosh.Connection;
import com.calclab.emite.core.client.packet.IPacket;
import com.calclab.emite.core.client.packet.Packet;
import com.calclab.emite.core.client.packet.gwt.GWTPacket;
import com.calclab.emite.core.client.xmpp.session.Session;
import com.calclab.emite.core.client.xmpp.session.Session.State;
import com.calclab.emite.core.client.xmpp.stanzas.IQ;
import com.calclab.emite.core.client.xmpp.stanzas.Message;
import com.calclab.emite.core.client.xmpp.stanzas.XmppURI;
import com.calclab.emite.core.client.xmpp.stanzas.Presence.Show;
import com.calclab.emite.im.client.presence.PresenceManager;
import com.calclab.emite.im.client.presence.PresenceManagerImpl;
import com.calclab.emite.im.client.roster.RosterImpl;
import com.calclab.suco.client.Suco;
import com.calclab.suco.client.events.Listener;
import com.google.gwt.xml.client.XMLParser;

public class GwtOswService implements OswService {

	private static GwtOswService instance;

	private final Session session = Suco.get(Session.class);

	private final ActivityFactory activityFactory = new DefaultActivityFactory();

	private final AclFactory aclFactory = new DefaultAclFactory();

	private final AtomFactory atomFactory = new DefaultAtomFactory();

	private final VCard4Factory profileFactory = new GwtProfileFactory();

	private final RelationFactory relationFactory = new DefaultRelationFactory();

	private final Map<String, Object> cache = new HashMap<String, Object>();

	private final GwtInbox inbox = new GwtInbox();

	private final QueryCache queryCache = new QueryCache();

	private RequestCallback<?> loginCallback;

	private RequestCallback<?> logoutCallback;

	private Map<String, UpdateCallback<UploadStatus>> uploadCallbacks = new HashMap<String, UpdateCallback<UploadStatus>>();

	private String domain;

	private Roster roster;

	private PresenceManager presenceManager;

	public static GwtOswService getInstance() {
		if (instance == null) {
			instance = new GwtOswService();
		}
		return instance;
	}

	@Override
	public AclFactory getAclFactory() {
		return aclFactory;
	}

	@Override
	public ActivityFactory getActivityFactory() {
		return activityFactory;
	}

	@Override
	public AtomFactory getAtomFactory() {
		return atomFactory;
	}

	@Override
	public VCard4Factory getProfileFactory() {
		return profileFactory;
	}

	@Override
	public RelationFactory getRelationFactory() {
		return relationFactory;
	}

	@Override
	public void setup(String httpBase, String hostname, String domain) {
		Suco.get(Connection.class).setSettings(
				new BoshSettings(httpBase, hostname));
		session.onStateChanged(new StateChangedListener());
		session.onMessage(new MessageListener());
		this.domain = domain;
	}

	@Override
	public void login(String username, String password,
			RequestCallback<Object> callback) {
		if (logoutCallback == null && loginCallback == null) {
			loginCallback = callback;
			RosterImpl rosterImpl = new RosterImpl(session);
			roster = new GwtRoster(rosterImpl);
			presenceManager = new PresenceManagerImpl(session, rosterImpl);
			session.login(XmppURI.uri(username + "@" + domain), password);
		}
	}

	@Override
	public void logout(RequestCallback<Object> callback) {
		if (logoutCallback == null && loginCallback == null) {
			logoutCallback = callback;
			session.logout();
		}
	}

	@Override
	public boolean isLoggedIn() {
		return session.isLoggedIn();
	}

	@Override
	public Stream<ActivityEntry> getInbox() {
		return inbox;
	}

	@Override
	public void getProfile(final String jid,
			final RequestCallback<Profile> callback) {
		// Hit the cache
		if (cache.containsKey("profile_" + jid)) {
			Object value = cache.get("profile_" + jid);
			if (value != null && value instanceof Profile) {
				callback.onSuccess((Profile) value);
			} else {
				callback.onFailure();
			}
			return;
		}

		// Check if ongoing query
		if (queryCache.hasQuery("profile_" + jid)) {
			queryCache.addCallback("profile_" + jid, new QueryCallback() {

				@Override
				public void onFailure() {
					callback.onFailure();
				}

				@Override
				public void onResult(Object result) {
					if (result != null && result instanceof Profile) {
						callback.onSuccess((Profile) result);
					} else {
						callback.onFailure();
					}
				}
			});
			return;
		}

		// No cache, new query
		queryCache.addQuery("profile_" + jid);
		IQ iq = new IQ(IQ.Type.get);
		iq.addQuery("http://onesocialweb.org/spec/1.0/vcard4#query");
		iq.setTo(XmppURI.jid(jid));
		session.sendIQ("osw", iq, new Listener<IPacket>() {

			public void onEvent(IPacket packet) {
				// Packet should not be an error
				if (IQ.isSuccess(packet)) {
					// Parse the packet and check if a proper query request
					final IPacket query = packet.getFirstChild("query");
					Profile profile = null;
					if (query != null && query.getChildrenCount() > 0) {
						// Parse the packet and return the profile
						IPacket item = query.getFirstChild("vcard");
						if (item instanceof GWTPacket) {
							GWTPacket i_packet = (GWTPacket) item;
							Element element = new ElementAdapter(i_packet
									.getElement());
							VCard4DomReader reader = new GwtVCard4DomReader();
							profile = reader.readProfile(element);
						}
					}

					if (profile == null) {
						profile = profileFactory.profile();
					}

					cache.put("profile_" + jid, profile);
					queryCache.success("profile_" + jid, profile);
					callback.onSuccess(profile);
					return;
				}

				// If we are here, there was an error
				cache.put("profile_" + jid, null);
				queryCache.failure("profile_" + jid);
				callback.onFailure();
			}
		});
	}

	@Override
	public void setProfile(final Profile profile,
			final RequestCallback<Object> callback) {
		VCard4DomWriter writer = new GwtVCard4DomWriter();
		Document document = new DocumentAdapter(XMLParser.createDocument());
		Element element = writer.toElement(profile, document);
		IQ iq = new IQ(IQ.Type.set);
		IPacket publish = iq.addChild("publish",
				"http://onesocialweb.org/spec/1.0/vcard4#publish");
		((Packet) publish).addChild(new GWTPacket(((ElementAdapter) element)
				.getGwtElement()));
		session.sendIQ("osw", iq, new Listener<IPacket>() {

			public void onEvent(IPacket packet) {
				// Check if no error
				if (IQ.isSuccess(packet)) {
					callback.onSuccess(null);
					cache.put("profile_" + getUserBareJID(), profile);
				} else {
					callback.onFailure();
				}
			}
		});
	}

	@Override
	public Stream<ActivityEntry> getActivities(String jid) {
		// Hit the cache
		if (cache.containsKey("activities_" + jid)) {
			Stream<ActivityEntry> activities = (GwtActivities) cache.get("activities_" + jid);
			activities.refresh(null);
			return activities;
		}

		// Create, cache, refresh and return
		GwtActivities activities = new GwtActivities(jid);
		activities.refresh(null);
		cache.put("activities_" + jid, activities);
		return activities;
	}

	@Override
	public void getRelations(final String jid,
			final RequestCallback<List<Relation>> callback) {
		IQ iq = new IQ(IQ.Type.get);
		iq.addQuery("http://onesocialweb.org/protocol/0.1/relations#query");
		iq.setTo(XmppURI.jid(jid));
		session.sendIQ("osw", iq, new Listener<IPacket>() {

			public void onEvent(IPacket packet) {
				// Check if not an error
				if (IQ.isSuccess(packet)) {
					// Parse the packet and check if a proper query request
					final IPacket query = packet.getFirstChild("query");
					final RelationDomReader reader = new GwtRelationDomReader();
					if (query != null && query.getChildrenCount() > 0) {
						// Parse the packet and store the notifications
						List<Relation> relations = new ArrayList<Relation>();
						for (IPacket item : query.getChildren()) {
{'fraction_non_alphanumeric': 0.11116414490955086, 'fraction_numerical': 0.003245668464512434, 'mean_word_length': 4.401392111368909, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 18}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2271897', 'n_tokens_mistral': 7389, 'n_tokens_neox': 6527, 'n_words': 1466}