Android Open Source - msf-spaces-sdk-android Space Handler






From Project

Back to project page msf-spaces-sdk-android.

License

The source code is released under:

Apache License

If you think the Android project msf-spaces-sdk-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package de.imc.mirror.sdk.android;
/*from w w  w  .ja  v  a2  s.c  om*/
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;

import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;
import org.jdom2.util.IteratorIterable;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromContainsFilter;
import org.jivesoftware.smack.filter.IQTypeFilter;
import org.jivesoftware.smack.filter.OrFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.smackx.packet.DiscoverItems;

import de.imc.mirror.sdk.ConnectionStatus;
import de.imc.mirror.sdk.ConnectionStatusListener;
import de.imc.mirror.sdk.OfflineModeHandler;
import de.imc.mirror.sdk.OrgaSpace;
import de.imc.mirror.sdk.Space;
import de.imc.mirror.sdk.Space.PersistenceType;
import de.imc.mirror.sdk.SpaceChannel;
import de.imc.mirror.sdk.SpaceConfiguration;
import de.imc.mirror.sdk.SpaceMember;
import de.imc.mirror.sdk.SpaceMember.Role;
import de.imc.mirror.sdk.config.NamespaceConfig;
import de.imc.mirror.sdk.exceptions.ConnectionStatusException;
import de.imc.mirror.sdk.exceptions.SpaceManagementException;
import de.imc.mirror.sdk.exceptions.SpaceManagementException.Type;
import de.imc.mirror.sdk.exceptions.UnknownEntityException;

import android.content.Context;
import android.util.Log;


/**
 * This class provides methods to create, modify, delete and retrieve spaces.
 * The class provides offline functionality, which can be accessed over the methods specified in
 * the {@link OfflineModeHandler} interface.
 * @author mach
 *
 */
public class SpaceHandler implements de.imc.mirror.sdk.OfflineModeHandler, de.imc.mirror.sdk.SpaceHandler {
  private int timeout = 2000;
  
  private ConnectionHandler connectionHandler;
  private Mode userWantedMode;
  private Mode realMode;
  private XMPPConnection connection;
  private String domain;
  private de.imc.mirror.sdk.UserInfo userInfo;
  private Map<String, RequestFuture<Element>> pendingSpacesRequests;
  private List<Space> spaces;
  private DataWrapper datawrapper;
  
  private PacketListener packetListener = new PacketListener(){

    @Override
    public void processPacket(Packet packet) {
      if (pendingSpacesRequests.containsKey(packet.getPacketID())) {
        RequestFuture<Element> spaceFuture = pendingSpacesRequests.get(packet.getPacketID());
        pendingSpacesRequests.remove(packet.getPacketID());
        Element element = parsePacketToElement(packet);
        if (element != null) {
          spaceFuture.setResponse(element);
        }
      }
    }
  };
  
  /**
   * Creates a new space handler.
   * @param context The current application context.
   * @param connectionHandler The current XMPP-connection.
   * @param dbName A name for the database the caches are saved in. If one was used and you want to use another one you should delete all application data.
   */
  public SpaceHandler(Context context, ConnectionHandler connectionHandler, String dbName){
    if (context == null || connectionHandler == null || dbName == null || dbName.trim().length() == 0){
      throw new IllegalArgumentException("None of the Arguments may be null.");
    }
    this.timeout = connectionHandler.getConfiguration().requestTimeout();
    this.userWantedMode = Mode.OFFLINE;
    this.connectionHandler = connectionHandler;
    this.connection = this.connectionHandler.getXMPPConnection();
    datawrapper = DataWrapper.getInstance(context, dbName);
    
    pendingSpacesRequests = new ConcurrentHashMap<String, RequestFuture<Element>>();
    this.userInfo = this.connectionHandler.getCurrentUser();
    this.spaces = new ArrayList<Space>();
    connectionHandler.addConnectionStatusListener(new ConnectionStatusListener() {
      
      @Override
      public void connectionStatusChanged(ConnectionStatus newStatus) {
        if (newStatus == ConnectionStatus.ONLINE){
          setRealMode(Mode.ONLINE);  
          prepareOnlineMode();
        } else {
          setRealMode(Mode.OFFLINE);
        }
      }
    });
    if (connectionHandler.getStatus() == ConnectionStatus.ONLINE){
      setRealMode(Mode.ONLINE);
    } else {
      setRealMode(Mode.OFFLINE);
    }
  }

  /**
   * Creates a private space for the current user.
   * @return Return The private space created for the current user.
   * @throws SpaceManagementException Failed to create default space. 
   * @throws ConnectionStatusException The handler needs to be ONLINE to perform this operation.
   */
  @Override
  public PrivateSpace createDefaultSpace()
    throws SpaceManagementException, ConnectionStatusException {
    if (getMode() == Mode.OFFLINE){
      throw new ConnectionStatusException("The handler has to be online to use this method.");
    }
    IQ iq = new IQ(){

      @Override
      public String getChildElementXML() {
        Element childElement = new Element("spaces", NamespaceConfig.SPACES_SERVICE);
        childElement.addContent(new Element("create", NamespaceConfig.SPACES_SERVICE));
        XMLOutputter out = new XMLOutputter();
        return out.outputString(childElement);
      }
    };
    iq.setType(IQ.Type.SET);
    iq.setFrom(userInfo.getFullJID());
    iq.setTo(connectionHandler.getNetworkInformation().getSpacesServiceJID());
    RequestFuture<Element> spaceFuture = new RequestFuture<Element>();
    pendingSpacesRequests.put(iq.getPacketID(), spaceFuture);
    connection.sendPacket(iq);
    Element response;
    try {
      response = spaceFuture.get(timeout, TimeUnit.MILLISECONDS);
      if (response != null){
        String type = response.getAttributeValue("type");
        if ("result".equalsIgnoreCase(type)){
          List<Element> elements = getChildren(response, "create");
          if (elements.size() != 1) {
            return null;
          }
          String spaceId = elements.get(0).getAttributeValue("space");
          PrivateSpace defaultSpace = new de.imc.mirror.sdk.android.PrivateSpace("", spaceId, connectionHandler.getConfiguration().getDomain());
          defaultSpace = (PrivateSpace) retrieveAllSpaceInformation(defaultSpace);
          
          return defaultSpace;
        }else if ("error".equalsIgnoreCase(type)){
          //TODO
          List<Element> error = getChildren(response, "text");
          if (error.size() > 0) {
            Log.d("SpaceHandler", error.get(0).getText());
          }
          throw new SpaceManagementException("An error response was received.",  SpaceManagementException.Type.OTHER);
        }
      }
    } catch (InterruptedException e) {
      throw new SpaceManagementException("Receiving a response was interrupted.", SpaceManagementException.Type.OTHER, e);
    } catch (ExecutionException e) {
      throw new SpaceManagementException("Couldn't receive a response.", SpaceManagementException.Type.OTHER, e);
    } catch (TimeoutException e) {
      throw new SpaceManagementException("Receiving a response timed out.", SpaceManagementException.Type.OTHER, e);
    }
    return null;
  }
  
  /**
   * Creates a space with the given configuration.
   * @param config Space configuration to apply.
   * @return Space created.
   * @throws SpaceManagementException Failed to create the space. 
   * @throws ConnectionStatusException The handler needs to be ONLINE to perform this operation.
   */
  @Override
  public Space createSpace(final SpaceConfiguration config) throws 
          SpaceManagementException, ConnectionStatusException {
    if (getMode() == Mode.OFFLINE){
      throw new ConnectionStatusException("The handler has to be online to use this method.");
    }
    checkConfiguration(config);
    IQ iq = new IQ(){

      @Override
      public String getChildElementXML() {
        Element childElement = new Element("spaces", NamespaceConfig.SPACES_SERVICE);
        childElement.addContent(new Element("create", NamespaceConfig.SPACES_SERVICE));
        Element configureElement = new Element("configure", NamespaceConfig.SPACES_SERVICE);
        Element xElement = new Element("x", NamespaceConfig.XMPP_DATA).setAttribute("type", "submit");
        Element fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "FORM_TYPE").setAttribute("type", "hidden");
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(NamespaceConfig.SPACES_SERVICE_CONFIG));
        xElement.addContent(fieldElement);
        
        fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "spaces#type");
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(config.getType().toString()));
        xElement.addContent(fieldElement);
        
        fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "spaces#persistent");
        String persistentString;
        switch (config.getPersistenceType()) {
        case ON:
          persistentString = "true";
          break;
        case DURATION:
          persistentString =  config.getPersistenceDuration().toString();
          break;
        default:
          persistentString = "false";
        }
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(persistentString));
        xElement.addContent(fieldElement);
        
        fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "spaces#name");
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(config.getName()));
        xElement.addContent(fieldElement);
        
        Element membersElement = new Element("field", NamespaceConfig.XMPP_DATA).setAttribute("var", "spaces#members");
        Element moderatorsElement = new Element("field", NamespaceConfig.XMPP_DATA).setAttribute("var", "spaces#moderators");
        for (SpaceMember member: config.getMembers()){
          switch(member.getRole()){
          case MEMBER:
            membersElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(member.getJID()));
            break;
          case MODERATOR:
            membersElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(member.getJID()));
            moderatorsElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(member.getJID()));
            
          }
        }
        xElement.addContent(membersElement);
        xElement.addContent(moderatorsElement);
        configureElement.addContent(xElement);
        childElement.addContent(configureElement);
        XMLOutputter out = new XMLOutputter();
        return out.outputString(childElement);
      }
    };
    iq.setType(IQ.Type.SET);
    iq.setTo(connectionHandler.getNetworkInformation().getSpacesServiceJID());
    iq.setFrom(userInfo.getFullJID());
    RequestFuture<Element> spaceFuture = new RequestFuture<Element>();
    pendingSpacesRequests.put(iq.getPacketID(), spaceFuture);
    connection.sendPacket(iq);
    Element response = null;
    try {
      response = spaceFuture.get(timeout, TimeUnit.MILLISECONDS);
      if (response != null){
        String type = response.getAttributeValue("type");
        if ("result".equalsIgnoreCase(type)){
          List<Element> elements = getChildren(response, "create");
          if (elements.size() != 1) {
            return null;
          }
          String spaceId = elements.get(0).getAttributeValue("space");
          Space space = de.imc.mirror.sdk.android.Space.createSpace(config.getName(), 
              spaceId, 
              connectionHandler.getConfiguration().getDomain(),
              null,
              config.getType(), 
              null, 
              config.getMembers(), 
              config.getPersistenceType(),
              config.getPersistenceDuration()
            );

          Space newSpace;
          newSpace = retrieveAllSpaceInformation(space);
          if (newSpace != null){
            for (SpaceMember member:config.getMembers()){
              if (member.getJID().equalsIgnoreCase(userInfo.getBareJID())){
                datawrapper.saveSpace(newSpace, userInfo.getBareJID());
                break;
              }
            }
            spaces.add(newSpace);
            return newSpace;
          }
          return space;
        }else if ("error".equalsIgnoreCase(type)){
          //TODO
          List<Element> error = getChildren(response, "text");
          if (error.size() > 0) {
            Log.d("SpaceHandler", error.get(0).getText());
          }
          throw new SpaceManagementException("An error response was received.",  SpaceManagementException.Type.OTHER);
        }
      }
    }catch (InterruptedException e) {
      throw new SpaceManagementException("Receiving a response was interrupted.", SpaceManagementException.Type.OTHER, e);
    } catch (ExecutionException e) {
      throw new SpaceManagementException("Couldn't receive a response.", SpaceManagementException.Type.OTHER, e);
    } catch (TimeoutException e) {
      throw new SpaceManagementException("Receiving a response timed out.", SpaceManagementException.Type.OTHER, e);
    }
    return null;
  }

  /**
   * Deletes the space with the given id.
   * @param spaceId Identifier of the space to delete.
   * @throws SpaceManagementException Failed to delete the space.
   * @throws ConnectionStatusException The handler needs to be ONLINE to perform this operation.
   */
  @Override
  public void deleteSpace(final String spaceId) throws SpaceManagementException, ConnectionStatusException{
    if (getMode() == Mode.OFFLINE){
      throw new ConnectionStatusException("You have to be in onlinemode to delete a Space");
    }
    Space space = this.getSpace(spaceId);
    if (space == null) {
      return;
    }
    if (!isModeratorOfSpace(userInfo.getBareJID(), space)) {
      throw new SpaceManagementException(userInfo.getUsername() + " is no moderator of space " + spaceId, SpaceManagementException.Type.NOT_AUTHORIZED);
    }
    IQ testIq = new IQ(){

      @Override
      public String getChildElementXML() {
        Element childElement = new Element("spaces", NamespaceConfig.SPACES_SERVICE);
        childElement.addContent(new Element("delete", NamespaceConfig.SPACES_SERVICE).setAttribute("space", spaceId));
        XMLOutputter out = new XMLOutputter();
        return out.outputString(childElement);
      }
      
    };
    String id = IQ.nextID();
    testIq.setType(IQ.Type.SET);
    testIq.setTo(connectionHandler.getNetworkInformation().getSpacesServiceJID());
    testIq.setFrom(userInfo.getFullJID());
    testIq.setPacketID(id);
    RequestFuture<Element> spaceFuture = new RequestFuture<Element>();
    pendingSpacesRequests.put(id, spaceFuture);
    connection.sendPacket(testIq);
    try{
    Element response = spaceFuture.get(timeout, TimeUnit.MILLISECONDS);
    if (response != null){
      String type = response.getAttributeValue("type");
      if ("result".equalsIgnoreCase(type)){
        datawrapper.deleteCachedSpace(spaceId);
      }
      else if ("error".equalsIgnoreCase(type)){
        //TODO
        List<Element> error = getChildren(response, "text");
        if (error.size() > 0) {
          Log.d("SpaceHandler", error.get(0).getText());
        }
        throw new SpaceManagementException("An error response was received.",  SpaceManagementException.Type.OTHER);
      }
    }
    } catch (InterruptedException e) {
      throw new SpaceManagementException("Receiving a response was interrupted.", SpaceManagementException.Type.OTHER, e);
    } catch (ExecutionException e) {
      throw new SpaceManagementException("Couldn't receive a response.", SpaceManagementException.Type.OTHER, e);
    } catch (TimeoutException e) {
      throw new SpaceManagementException("Receiving a response timed out.", SpaceManagementException.Type.OTHER, e);
    }
  }
  
  /**
   * Retrieves the configuration of the space.
   * @param space The space to get the configuration for.
   * @return The parsed result or, if there was an error, null.
   * @throws SpaceManagementException Thrown when no response was received from the server.
   */
  private SpaceConfiguration getSpaceConfiguration(Space space) throws SpaceManagementException{
    if (space == null){
      throw new IllegalArgumentException("The given space must not be null");
    }
    ServiceDiscoveryManager discoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
    DiscoverInfo info;
    try {
      info = discoveryManager.discoverInfo(SERVICE_PREFIX + space.getDomain(), space.getId());
    } catch (XMPPException e) {
      if (e.getXMPPError().getCode() == 404) {
        return null;
      } else {
        throw new SpaceManagementException("The Server didn't respond.", Type.OTHER, e);
      }
    }
    Element config = parsePacketToElement(info);
    return parseSpaceConfiguration(config);
  }

  /**
   * Checks if the given user is a moderator of the given space.
   * @param user The user to check.
   * @param space The space to check.
   * @return If the user is an moderator of the given space. If offline, it returns <code>false</code>
   */
  private boolean isModeratorOfSpace(String user, Space space){
    if (getMode() == Mode.OFFLINE) {
      return false;
    }
    if (space != null){
      Set<SpaceMember> members = space.getMembers();
      if (members != null){
        for (SpaceMember member:members){
          if (member.getJID().equalsIgnoreCase(user.split("/")[0])){
            if (member.getRole() == Role.MODERATOR){
              return true;
            } else return false;
          }
        }
      }
    }
    return false;
  }
  
  /**
   * Checks if the given user is a moderator of the given space.
   * @param user The user to check.
   * @param spaceId The id of the space to check.
   * @return If the user is an moderator of the given space. If offline, it returns <code>false</code>
   * @throws UnknownEntityException The given space does not exist.
   */
  public boolean isModeratorOfSpace(String user, String spaceId) throws UnknownEntityException {
    //Lazy getSpace?
    Space space = getSpace(spaceId);
    if (space != null) {
      return isModeratorOfSpace(user, space);
    } else {
      throw new UnknownEntityException("No space could be retrieved for id: " + spaceId);
    }
  }
  
  /**
   * Checks if a SpaceConfiguration is wellformed.
   * @param config The SpaceConfiguration to check.
   */
  private void checkConfiguration(SpaceConfiguration config) {
    if (config.getName().length() <= 0){
      throw new IllegalArgumentException("The name may not be empty.");
    }
    if (config.getType().equals(Space.Type.OTHER)){
      throw new IllegalArgumentException("You can only create spaces of the type private, team or orga.");
    }
    if (config.getMembers().size() <= 0){
      throw new IllegalArgumentException("A space needs at least one member.");
    }
    boolean hasModerator = false;
    for (SpaceMember member:config.getMembers()){
      if (member.getRole().equals(Role.MODERATOR)){
        hasModerator = true;
        break;
      }
    }
    if (!hasModerator){
      throw new IllegalArgumentException("A space needs at least one Moderator.");
    }
  }
  
  /**
   * Tries to apply a configuration to a space.
   * @param spaceId Identifier of the space to apply configuration on. 
   * @param config Space configuration to apply.
   * @return Space after the configuration was successfully applied.
   * @throws SpaceManagementException Failed to apply space configuration.
   * @throws ConnectionStatusException The handler needs to be ONLINE to perform this operation.
   */
  @Override
  public Space configureSpace(final String spaceId, final SpaceConfiguration config) throws 
    SpaceManagementException, ConnectionStatusException {
    if (getMode() == Mode.OFFLINE){
      throw new ConnectionStatusException("Invalid online status. The handler must be online in order to perform this task.");
    }
    Space space = getSpace(spaceId);
    if (space == null) {
      throw new SpaceManagementException("The given space does not exist: " + spaceId, SpaceManagementException.Type.OTHER);
    }
    if (!space.isModerator(userInfo.getBareJID())) {
      throw new SpaceManagementException("The user is no moderator of this space", SpaceManagementException.Type.NOT_AUTHORIZED);
    }
    checkConfiguration(config);
    IQ modifyIq = new IQ(){
      @Override
      public String getChildElementXML() {
        Element childElement = new Element("spaces", NamespaceConfig.SPACES_SERVICE);
        Element configureElement = new Element("configure", NamespaceConfig.SPACES_SERVICE);
        configureElement.setAttribute("space", spaceId);
        childElement.addContent(configureElement);
        Element xElement = new Element("x", NamespaceConfig.XMPP_DATA);
        xElement.setAttribute("type", "submit");
        configureElement.addContent(xElement);
        Element fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "FORM_TYPE").setAttribute("type", "hidden");
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(NamespaceConfig.SPACES_SERVICE_CONFIG));
        xElement.addContent(fieldElement);
        
        fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "spaces#type");
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(config.getType().toString()));
        xElement.addContent(fieldElement);
        
        fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "spaces#persistent");
        String persistentString;
        switch (config.getPersistenceType()) {
        case ON:
          persistentString = "true";
          break;
        case DURATION:
          persistentString = config.getPersistenceDuration().toString();
          break;
        default:
          persistentString = "false";
        }
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(persistentString));
        xElement.addContent(fieldElement);
        
        fieldElement = new Element("field", NamespaceConfig.XMPP_DATA);
        fieldElement.setAttribute("var", "spaces#name");
        fieldElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(config.getName()));
        xElement.addContent(fieldElement);
        

        Element membersElement = new Element("field", NamespaceConfig.XMPP_DATA).setAttribute("var", "spaces#members");
        Element moderatorsElement = new Element("field", NamespaceConfig.XMPP_DATA).setAttribute("var", "spaces#moderators");
        for (SpaceMember member: config.getMembers()){
          switch(member.getRole()){
          case MEMBER:
            membersElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(member.getJID()));
            break;
          case MODERATOR:
            membersElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(member.getJID()));
            moderatorsElement.addContent(new Element("value", NamespaceConfig.XMPP_DATA).setText(member.getJID()));
            
          }
        }
        xElement.addContent(membersElement);
        xElement.addContent(moderatorsElement);
      
        XMLOutputter out = new XMLOutputter();
        return out.outputString(childElement);
      }
      
    };
    String id = IQ.nextID();
    modifyIq.setType(IQ.Type.SET);
    modifyIq.setTo(SERVICE_PREFIX + space.getDomain());
    modifyIq.setFrom(userInfo.getFullJID());
    modifyIq.setPacketID(id);
    RequestFuture<Element> spaceFuture = new RequestFuture<Element>();
    pendingSpacesRequests.put(id, spaceFuture);
    connection.sendPacket(modifyIq);
    Element response;
    try {
      response = spaceFuture.get(timeout, TimeUnit.MILLISECONDS);
      if (response != null){
        String type = response.getAttributeValue("type");
        if ("result".equalsIgnoreCase(type)){
          return getSpace(space.getId());
        }
        else if ("error".equalsIgnoreCase(type)){
          //TODO
          List<Element> error = getChildren(response, "text");
          if (error.size() > 0) {
            Log.d("SpaceHandler", error.get(0).getText());
          }
          throw new SpaceManagementException("An error response was received.",  SpaceManagementException.Type.OTHER);
        }
      }
    } catch (InterruptedException e) {
      throw new SpaceManagementException("Receiving a response was interrupted.", SpaceManagementException.Type.OTHER, e);
    } catch (ExecutionException e) {
      throw new SpaceManagementException("Couldn't receive a response.", SpaceManagementException.Type.OTHER, e);
    } catch (TimeoutException e) {
      throw new SpaceManagementException("Receiving a response timed out.", SpaceManagementException.Type.OTHER, e);
    }
    return null;
  }
  
  /**
   * Parses a received Element of the configuration of a space.
   * @param configElement The iq of the configuration of a space.
   * @return A SpaceConfiguration object with the data of the space, or null if something is wrong.
   */
  private SpaceConfiguration parseSpaceConfiguration(Element configElement){
    List<Element> fields;
    if (configElement == null || (fields = getChildren(configElement, "field")) == null || fields.size() == 0){
      return null;
    }
    else {
      Set<SpaceMember> spaceMembers = new HashSet<SpaceMember>();
      Set<String> moderators = new HashSet<String>();
      Set<String> members = new HashSet<String>();
      Space.Type type = null;
      PersistenceType persistenceType = PersistenceType.OFF;
      Duration persistenceDuration = null;
      String name = null;
      for (Element field:fields){
        String var = field.getAttributeValue("var");
        if ("spaces#type".equals(var)){
          type = Space.Type.getType(field.getChildText("value", field.getNamespace()));
        } else if ("spaces#persistent".equals(var)) {
          String persistentString = field.getChildText("value", field.getNamespace());
          if ("true".equalsIgnoreCase(persistentString) || "1".equals(persistentString)) {
            persistenceType = PersistenceType.ON;
            persistenceDuration = null;
          } else if ("false".equalsIgnoreCase(persistentString) || "0".equals(persistentString)) {
            // keep defaults
          } else {
            try {
              persistenceDuration = DatatypeFactory.newInstance().newDuration(persistentString);
              persistenceType = PersistenceType.DURATION;
            } catch (Exception e) {
              // keep defaults
            }
          }
        } else if ("spaces#name".equals(var)){
          name = field.getChildText("value", field.getNamespace());
        } else if ("spaces#members".equals(var)){
          List<Element> values = getChildren(field, "value");
          for (Element value:values){
            members.add(value.getText());
          }
        } else if ("spaces#moderators".equals(var)){
          List<Element> values = getChildren(field, "value");
          for (Element value:values){
            moderators.add(value.getText());
          }
        }
      }
      members.removeAll(moderators);
      for (String member:members){
        spaceMembers.add(new de.imc.mirror.sdk.android.SpaceMember(member, Role.MEMBER));
      }
      for (String moderator:moderators){
        spaceMembers.add(new de.imc.mirror.sdk.android.SpaceMember(moderator, Role.MODERATOR));
      }
      SpaceConfiguration config = new de.imc.mirror.sdk.android.SpaceConfiguration(type,name, spaceMembers, persistenceType, persistenceDuration);
      return config;
    }
  }
  
  /**
   * Parses the given space info to retrieve the id of the pubsub-node and -service
   * and the id of the MUC if available.
   * @param spaceInfo The parsed Element of the spaceinfo.
   * @param space The corresponding space.
   * @return The space with the set infos.
   */
  private Space parseSpaceChannels(Element spaceInfo, Space space){
    List<Element> channels = getChildren(spaceInfo, "channel");
    if (channels == null || channels.size() == 0){
      return null;
    }
    Set<SpaceChannel> channelsList = new HashSet<SpaceChannel>();
    for (Element channel: channels){
      Map<String, String> properties = new HashMap<String, String>();
      String type = channel.getAttributeValue("type");
      List<Element> children = getChildren(channel, "property");
      for (Element property : children) {
        properties.put(property.getAttributeValue("key"), property.getText());
      }
      channelsList.add(new de.imc.mirror.sdk.android.SpaceChannel(type, properties));
    }
    Space result = de.imc.mirror.sdk.android.Space.createSpace(
      space.getName(), 
      space.getId(), 
      space.getDomain(), 
      null, 
      space.getType(), 
      channelsList, 
      space.getMembers(), 
      space.getPersistenceType(),
      space.getPersistenceDuration()
    );
    return result;
  }
  
  /**
   * Setter for the XMPPConnection. Use this only when you create a new connection object.
   * @param connectionHandler The XMPPConnection object this instance of a SpaceHandler should use.
   * @throws SpaceManagementException Thrown when there's no response from the server.
   */
  public void changeConnectionHandler(ConnectionHandler connectionHandler) throws SpaceManagementException {
    this.connectionHandler = connectionHandler;
    this.connection = this.connectionHandler.getXMPPConnection();

    if (connectionHandler.getNetworkInformation().getSpacesServiceJID() != null){
      AndFilter andFilter = new AndFilter();
      OrFilter orFilter = new OrFilter();
      orFilter.addFilter(new IQTypeFilter(IQ.Type.ERROR));
      orFilter.addFilter(new IQTypeFilter(IQ.Type.RESULT));
      andFilter.addFilter(orFilter);
      andFilter.addFilter(new FromContainsFilter(connectionHandler.getNetworkInformation().getSpacesServiceJID()));
      this.connection.addPacketListener(packetListener, andFilter);
    }
  }
  
  /**
   * Requests the spaces which are available for the user.
   * @return List<Space> A List of all available spaces, with each having their name, id and domain set.
   * @throws SpaceManagementException Thrown when there's an error response from the server.
   */
  private List<Space> retrieveAvailableSpaces() throws SpaceManagementException{
    if (getMode() == Mode.OFFLINE || connectionHandler.getNetworkInformation().getSpacesServiceJID() == null){
      return null;
    }
    List<Space> spacesList = new ArrayList<Space>();
    ServiceDiscoveryManager discoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
    DiscoverItems itemsInfo;
    try {
      itemsInfo = discoveryManager.discoverItems(connectionHandler.getNetworkInformation().getSpacesServiceJID());
    } catch (XMPPException e) {
      throw new SpaceManagementException("Server didn't respond.", Type.OTHER, e);
    }
    Element element = parsePacketToElement(itemsInfo);
    if ("result".equalsIgnoreCase(element.getAttributeValue("type"))){
      List<Element> items = getChildren(element, "item");
      if (items != null){
        for (Element item:items){
          String domain = item.getAttributeValue("jid").replace(SERVICE_PREFIX, "");
          String[] node = item.getAttributeValue("node").split("#");
          Space.Type type;
          if (node.length>=2){
            type = Space.Type.getType(node[0]);
            if (type == Space.Type.OTHER){
              type = Space.Type.PRIVATE;
            }
          } else {
            type = Space.Type.PRIVATE;
          }
          spacesList.add(
            de.imc.mirror.sdk.android.Space.createSpace(
                item.getAttributeValue("name"),
                item.getAttributeValue("node"),
                domain,
                null,
                type,
                null,
                null,
                PersistenceType.OFF,
                null)
          );
        }
      }
    } //TODO error possible??
    /*else if (iq.getType().equals("error")){
      Log.d("SpaceHandler", iq.error.text.text);
      throw new SpaceManagementException("An error response was received.",  SpaceManagementException.Type.OTHER);
    }*/
    return spacesList;
  }

  /**
   * Requests the channels of the given space.
   * @param space The space to get the channels for.
   * @return The space with the set infos.
   * @throws SpaceManagementException Thrown when an error occurred while retrieving the channels.
   */
  private Space retrieveSpaceChannels(final Space space) throws SpaceManagementException{
    IQ channelsIq = new IQ() {
      
      @Override
      public String getChildElementXML() {
        Element childElement = new Element("spaces", NamespaceConfig.SPACES_SERVICE);
        Element channelsElement = new Element("channels", NamespaceConfig.SPACES_SERVICE);
        channelsElement.setAttribute("space", space.getId());
        childElement.addContent(channelsElement);
        XMLOutputter out = new XMLOutputter();
        return out.outputString(childElement);
      }
    };
    channelsIq.setType(IQ.Type.GET);
    channelsIq.setTo(connectionHandler.getNetworkInformation().getSpacesServiceJID());
    RequestFuture<Element> channelsFuture = new RequestFuture<Element>();
    pendingSpacesRequests.put(channelsIq.getPacketID(), channelsFuture);
    connection.sendPacket(channelsIq);
    Element response;
    try {
      response = channelsFuture.get(timeout, TimeUnit.MILLISECONDS);
      return parseSpaceChannels(response, space);
    } catch (InterruptedException e) {
      throw new SpaceManagementException("Receiving a response was interrupted.", SpaceManagementException.Type.OTHER, e);
    } catch (ExecutionException e) {
      throw new SpaceManagementException("Couldn't receive a response.", SpaceManagementException.Type.OTHER, e);
    } catch (TimeoutException e) {
      throw new SpaceManagementException("Receiving a response timed out.", SpaceManagementException.Type.OTHER, e);
    }
  }

  /**
   * Gets all Information of a space.
   * @param space The Space to get Information on.
   * @return A new space with all information set or <code>null</code> if no such space exists.
   * @throws SpaceManagementException Thrown when an error occured.
   */
  private Space retrieveAllSpaceInformation(Space space) throws SpaceManagementException{
    SpaceConfiguration config = getSpaceConfiguration(space);
    if (config == null) {
      return null;
    }
    space = retrieveSpaceChannels(space);
    Set<de.imc.mirror.sdk.DataModel> dataModels = new HashSet<de.imc.mirror.sdk.DataModel>();
    if (space.getType() == Space.Type.ORGA){
      try {
        Set<de.imc.mirror.sdk.DataModel> models = retrieveSupportedDataModels(space);
        if (models != null) {
          dataModels.addAll(models);
        }
      } catch (ConnectionStatusException e) {
        Log.d("SpaceHandler", "A ConnectionStatusException was thrown while trying to retrieve the supported DataModels.", e);
      }
    }
    return de.imc.mirror.sdk.android.Space.createSpace(config.getName(), space.getId(), space.getDomain(), dataModels, config.getType(),
            space.getChannels(), config.getMembers(), config.getPersistenceType(), config.getPersistenceDuration());
  }

  /**
   * Sends an request to the server to get the supported data models of the given space
   * @param space The space to get the data models for
   * @return Map<namespace, List<Schemalocation>>
   * @throws SpaceManagementException Thrown when an error occured while retrieving the DataModels.
   * @throws ConnectionStatusException You have to be in onlineMode to use this method.
   */
  private Set<de.imc.mirror.sdk.DataModel> retrieveSupportedDataModels(final Space space)throws SpaceManagementException, ConnectionStatusException{
    if (getMode() == Mode.OFFLINE){
      throw new ConnectionStatusException("You have to be online to retrieve datamodels");
    }
    if (!Space.Type.ORGA.equals(space.getType())){
      throw new IllegalArgumentException("The given space is no organizatorial space");
    }
    IQ modelsIq = new IQ() {
      
      @Override
      public String getChildElementXML() {
        Element childElement = new Element("spaces", NamespaceConfig.SPACES_SERVICE);
        Element modelsElement = new Element("models", NamespaceConfig.SPACES_SERVICE);
        modelsElement.setAttribute("space", space.getId());
        childElement.addContent(modelsElement);
        XMLOutputter out = new XMLOutputter();
        return out.outputString(childElement);
      }
    };
    modelsIq.setType(IQ.Type.GET);
    modelsIq.setTo(connectionHandler.getNetworkInformation().getSpacesServiceJID());
    String id = IQ.nextID();
    modelsIq.setPacketID(id);
    RequestFuture<Element> modelsFuture = new RequestFuture<Element>();
    pendingSpacesRequests.put(id, modelsFuture);
    connection.sendPacket(modelsIq);
    try{
    Element response = modelsFuture.get(timeout, TimeUnit.MILLISECONDS);
    List<Element> models = getChildren(response, "model");
    if (models.size() == 0){
      return null;
    }
    else if ("error".equalsIgnoreCase(response.getAttributeValue("type"))){
      //TODO
      List<Element> error = getChildren(response, "text");
      if (error.size() > 0) {
        Log.d("SpaceHandler", error.get(0).getText());
      }
      throw new SpaceManagementException("An error response was received.",  SpaceManagementException.Type.OTHER);
    }
    Set<de.imc.mirror.sdk.DataModel> dataModels = new HashSet<de.imc.mirror.sdk.DataModel>();
    for (Element model:models){
      dataModels.add(new DataModel(model.getAttributeValue("namespace"), model.getAttributeValue("schemaLocation")));
    }
    return dataModels;
    }catch (InterruptedException e) {
      throw new SpaceManagementException("Receiving a response was interrupted.", SpaceManagementException.Type.OTHER, e);
    } catch (ExecutionException e) {
      throw new SpaceManagementException("Couldn't receive a response.", SpaceManagementException.Type.OTHER, e);
    } catch (TimeoutException e) {
      throw new SpaceManagementException("Receiving a response timed out.", SpaceManagementException.Type.OTHER, e);
    }
  }

  /**
   * Sets the data models supported by an organizational space.
   * Performing this operation on spaces of types other than Space.Type.ORGA will fail.
   * Only data objects instantiating one of the supported data models may be published on this space. 
   * @param spaceId Identifier of the organizational space to set list of supported models for.
   * @param dataModels Set of data models to support.
   * @return Space after the setting has been successfully applied.
   * @throws SpaceManagementException Failed to apply setting, e.g., because the space is not of type Space.Type.ORGA.
   * @throws ConnectionStatusException The handler needs to be ONLINE to perform this operation.
   */
  @Override
  public OrgaSpace setModelsSupportedBySpace(String spaceId, final Set<de.imc.mirror.sdk.DataModel> dataModels) throws SpaceManagementException, ConnectionStatusException{
    if (getMode() == Mode.OFFLINE){
      throw new ConnectionStatusException("You have to be online to set datamodels");
    }
    final OrgaSpace space = (OrgaSpace)getSpace(spaceId +"");
    if (!Space.Type.ORGA.equals(space.getType())){
      throw new IllegalArgumentException("The given space is no organizatorial space");
    }
    if (!isModeratorOfSpace(userInfo.getBareJID(), space)){
      throw new SpaceManagementException("The user " + userInfo.getUsername() + " is no moderator of the space " + space.getId(), SpaceManagementException.Type.NOT_AUTHORIZED);
    }
    IQ modelsIq = new IQ() {
      
      @Override
      public String getChildElementXML() {

        Element childElement = new Element("spaces", NamespaceConfig.SPACES_SERVICE);
        Element modelsElement = new Element("models", NamespaceConfig.SPACES_SERVICE);
        modelsElement.setAttribute("space", space.getId());
        for (de.imc.mirror.sdk.DataModel model:dataModels){
          Element modelElement = new Element("model", NamespaceConfig.SPACES_SERVICE);
          modelElement.setAttribute("namespace", model.getNamespace());
          modelElement.setAttribute("schemaLocation", model.getSchemaLocation());
          modelsElement.addContent(modelElement);
        }
        childElement.addContent(modelsElement);
        XMLOutputter out = new XMLOutputter();
        return out.outputString(childElement);
      }
    };
    modelsIq.setType(IQ.Type.SET);
    modelsIq.setTo(connectionHandler.getNetworkInformation().getSpacesServiceJID());
    String id = IQ.nextID();
    modelsIq.setPacketID(id);
    RequestFuture<Element> modelsFuture = new RequestFuture<Element>();
    pendingSpacesRequests.put(id, modelsFuture);
    connection.sendPacket(modelsIq);
    Element response = null;
    try{
    response = modelsFuture.get(timeout, TimeUnit.MILLISECONDS);
    if (response == null){
      return null;
    }
    else if ("error".equalsIgnoreCase(response.getAttributeValue("type"))){
      //TODO
      List<Element> error = getChildren(response, "text");
      if (error.size() > 0) {
      Log.d("SpaceHandler", error.get(0).getText());
      }
      throw new SpaceManagementException("An error response was received.",  SpaceManagementException.Type.OTHER);
    }
    OrgaSpace orga = new de.imc.mirror.sdk.android.OrgaSpace(space.getName(), 
                                spaceId +"", 
                                space.getDomain(), 
                                dataModels, 
                                space.getChannels(),
                                space.getMembers(),
                                space.getPersistenceType(),
                                space.getPersistenceDuration());
    return orga;
    }catch (InterruptedException e) {
      throw new SpaceManagementException("Receiving a response was interrupted.", SpaceManagementException.Type.OTHER, e);
    } catch (ExecutionException e) {
      throw new SpaceManagementException("Couldn't receive a response.", SpaceManagementException.Type.OTHER, e);
    } catch (TimeoutException e) {
      throw new SpaceManagementException("Receiving a response timed out.", SpaceManagementException.Type.OTHER, e);
    }
  }
  
  /**
   * Called when the mode provided by the connection is changed to online or the user sets the mode to online.
   * If Handler is in onlinemode some preparations are done like checking and perhaps retrieving the spaces service adress.
   */
  private void prepareOnlineMode(){
    if (getMode() == Mode.ONLINE){
      if (domain == null){
        domain = userInfo.getDomain();
      }
      if (connectionHandler.getNetworkInformation().getSpacesServiceJID() != null) {
        this.connection.removePacketListener(packetListener);
        AndFilter andFilter = new AndFilter();
        OrFilter orFilter = new OrFilter();
        orFilter.addFilter(new IQTypeFilter(IQ.Type.ERROR));
        orFilter.addFilter(new IQTypeFilter(IQ.Type.RESULT));
        andFilter.addFilter(orFilter);
        andFilter.addFilter(new FromContainsFilter(connectionHandler.getNetworkInformation().getSpacesServiceJID()));
        this.connection.addPacketListener(packetListener, andFilter);
      }
    }
  }

  /**
   * Sets the mode for the handler.
   * @param mode Mode to set. 
   */
  @Override
  public void setMode(Mode mode){
    this.userWantedMode = mode;
    if (userWantedMode == Mode.ONLINE){
      prepareOnlineMode();
    }
  }
  
  /**
   * Returns the current mode of the handler.
   * Note: the current mode is dependant on the mode the user set and the current connectionstatus.
   * @return Mode.ONLINE or Mode.OFFLINE.
   */
  @Override
  public Mode getMode() {
    if (userWantedMode == Mode.OFFLINE){
      return userWantedMode;
    } else {
      return realMode;
    }
  }
  
  /**
   * Sets the current mode provided by the Connection;
   * @param mode Mode to set.
   */
  private void setRealMode(Mode mode){
    this.realMode = mode;
  }

  /**
   * Returns a list of all spaces available to the user.
   * ONLINE mode: The information is retrieved from the server, the local cache is updated, and the information is returned.
   * OFFLINE mode: The the information available in the local cache is returned.
   * @return Unmodifiable list containing all spaces available to the user. May be empty.
   */
  @Override
  public List<Space> getAllSpaces() {  
    List<Space> result = new ArrayList<Space>();
    if (getMode() == Mode.ONLINE){
      try {
      List<Space> spacesList = retrieveAvailableSpaces();  
      if (spacesList == null){
        return null;
      }
      for (Space space:spacesList){
        space = retrieveAllSpaceInformation(space);
        result.add(space);
      }
      datawrapper.deleteCachedSpacesForUser(userInfo.getBareJID());
      datawrapper.saveSpaces(result, userInfo.getBareJID());
      } catch (SpaceManagementException e) {
        Log.d("SpaceHandler", "A SpaceManagementException was thrown while retrieving all spaces.", e);
      } 
    } else {
      spaces = datawrapper.getCachedSpacesForUser(userInfo.getBareJID());
      return Collections.unmodifiableList(spaces);
    }
    return Collections.unmodifiableList(result);
  }

  /**
   * Returns the private space of the user. 
   * ONLINE mode: The information is retrieved from the server, the local cache is updated, and the information is returned.
   * OFFLINE mode: The the information available in the local cache is returned.
   * @return Private space of the user or <code>null</code> if no private space is set up.
   */
  @Override
  public PrivateSpace getDefaultSpace() {
    return (PrivateSpace) getSpace(userInfo.getUsername());
  }

  /**
   * Returns a specific space.
   * ONLINE mode: The information is retrieved from the server, the local cache is updated, and the information is returned.
   * OFFLINE mode: The the information from the local cache is returned if available.
   * @param spaceId Identifier of the space to retrieve.
   * @return Space with the given id or <code>null</code> if no space with such an id is available for the user.
   */
  @Override
  public Space getSpace(String spaceId) {
    if (getMode() == Mode.ONLINE) {
      Space space;
      Space.Type type;
      if (spaceId.contains("team#")) {
        type = Space.Type.TEAM;
      } else if (spaceId.contains("orga#")) {
        type = Space.Type.ORGA;
      } else {
        type = Space.Type.PRIVATE;
      }
      space = de.imc.mirror.sdk.android.Space.createSpace(null, 
                                spaceId, 
                                userInfo.getDomain(), 
                                null, 
                                type, 
                                null, 
                                null, 
                                PersistenceType.OFF, 
                                null);
      Space result;
      try {
        result = retrieveAllSpaceInformation(space);
        if (result == null) {
          return null;
        }
        if (datawrapper.isSpaceAlreadyCached(spaceId)){
          datawrapper.updateCachedSpaceInformation(result);
        } else datawrapper.saveSpace(result, userInfo.getBareJID());
      } catch (SpaceManagementException e) {
        Log.d("SpaceHandler", "A SpaceManagementException was thrown while retrieving a single space.", e);
        result = null;
      }
      return result;
    } else {
      spaces = datawrapper.getCachedSpacesForUser(userInfo.getBareJID());
      for (Space space:spaces){
        if (space.getId().equalsIgnoreCase(spaceId)){
          return space;
        }
      }
    }
    return null;
  }
  
  /**
   * Returns the list of spaces which are cached locally. 
   * @return List of cached spaces, may be empty.
   */
  protected List<Space> getCachedSpaces() {
    return datawrapper.getCachedSpacesForUser(userInfo.getBareJID());
  }

  /**
   * Returns a map containing the space identifiers and names for all spaces available to the user.
   * ONLINE mode: The information is retrieved from the server and the information is returned.
   * OFFLINE mode: The the information available in the local cache is returned.
   * Requesting the list without spaces details is faster and should be preferred to <code>SpacesManager.getAllSpaces()</code> whenever possible.
   * @return Unmodifiable map of space identifiers and related space names.
   */
  @Override
  public Map<String, String> getSpacesList() {
    Map<String, String> spacesMap = new HashMap<String, String>();
    if (getMode() == Mode.ONLINE){
      try {
        List<Space> spacesList = retrieveAvailableSpaces();
        for (Space space:spacesList){
          spacesMap.put(space.getId(), space.getName());
        }
        return Collections.unmodifiableMap(spacesMap);
      } catch (SpaceManagementException e) {
        Log.d("SpaceHandler", "A SpaceManagementException was thrown while retrieving a list of all spaces.", e);
      }
    }
    spaces = datawrapper.getCachedSpacesForUser(userInfo.getBareJID());
    for (Space space:spaces){
      spacesMap.put(space.getId(), space.getName());
    }
    return Collections.unmodifiableMap(spacesMap);
  }

  /**
   * Deletes locally stored data.
   */
  @Override
  public void clear() {
    datawrapper.clearSpacesCache();  
  }
  
  /**
   * Convenience method to parse an Packet to an JDOMElement.
   * @param packet The packet to parse.
   * @return The parsed JDOMElement.
   */
  private Element parsePacketToElement(Packet packet){
    SAXBuilder reader = new SAXBuilder();
    StringReader in = new StringReader(packet.toXML());
    Document document = null;
    try {
    document = reader.build(in);
    } catch (JDOMException e) {
      Log.d("SpaceHandler", "An JDOMException was thrown while parsing a newly gotten item.", e);
    } catch (IOException e) {
      Log.d("SpaceHandler", "An IOException was thrown while parsing a newly gotten item.", e);
    }
    if (document == null){
      return null;
    }
    Element elem = document.getRootElement();
    return elem;
  }
  
  private List<Element> getChildren(Element parentElement, String tagName) {
    IteratorIterable<Content> iter = parentElement.getDescendants();
    List<Element> children = new ArrayList<Element>();
    while (iter.hasNext()) {
      Element elem;
      try {
        elem = (Element) iter.next();
      } catch (ClassCastException e) {
        continue;
      }
      if (tagName.equalsIgnoreCase(elem.getName())) {
        children.add(elem);
      }
    }
    return children;
  }
  
  /**
   * This method returns the pubsub channel of a space.
   * It first tries to get them from the local cache, if that fails it tries to get them from the server.
   * @param spaceId The Id of the space to get the Node and Domain for.
   * @return The pubsub channel of the space.
   * @throws UnknownEntityException A space with the given ID is not available for the current user.
   */
  protected SpaceChannel getPubSubChannel(String spaceId) throws UnknownEntityException {
    // Try to retrieve data from cache. 
    List<Space> spacesList = datawrapper.getCachedSpacesForUser(userInfo.getBareJID());
    for (Space space:spacesList) {
      if (space.getId().equalsIgnoreCase(spaceId)){
        return space.getPubSubChannel();
      }
    }
    
    // Request data.
    if (getMode() == Mode.ONLINE) {
      Space space = getSpace(spaceId);
      if (space != null && space.getId().equalsIgnoreCase(spaceId)) {
        return space.getPubSubChannel();
      } else {
        throw new UnknownEntityException("No space with ID " + spaceId + " available.");
      }
    } else {
      throw new UnknownEntityException("OFFLINE mode: No space with ID " + spaceId + " cached.");
    }
  }
}




Java Source Code List

de.imc.mirror.sdk.android.CDMDataBuilder.java
de.imc.mirror.sdk.android.CDMData.java
de.imc.mirror.sdk.android.CommandType.java
de.imc.mirror.sdk.android.ConnectionConfigurationBuilder.java
de.imc.mirror.sdk.android.ConnectionConfiguration.java
de.imc.mirror.sdk.android.ConnectionHandler.java
de.imc.mirror.sdk.android.DataHandler.java
de.imc.mirror.sdk.android.DataModel.java
de.imc.mirror.sdk.android.DataObjectBuilder.java
de.imc.mirror.sdk.android.DataObject.java
de.imc.mirror.sdk.android.DataWrapper.java
de.imc.mirror.sdk.android.NetworkInformation.java
de.imc.mirror.sdk.android.OrgaSpace.java
de.imc.mirror.sdk.android.PrivateSpace.java
de.imc.mirror.sdk.android.ProviderInitializer.java
de.imc.mirror.sdk.android.RequestFuture.java
de.imc.mirror.sdk.android.SpaceChannel.java
de.imc.mirror.sdk.android.SpaceConfiguration.java
de.imc.mirror.sdk.android.SpaceHandler.java
de.imc.mirror.sdk.android.SpaceMember.java
de.imc.mirror.sdk.android.Space.java
de.imc.mirror.sdk.android.SpacesProvider.java
de.imc.mirror.sdk.android.TeamSpace.java
de.imc.mirror.sdk.android.UserInfo.java
de.imc.mirror.sdk.android.cdm.CDMData_0_1.java
de.imc.mirror.sdk.android.cdm.CDMData_0_2.java
de.imc.mirror.sdk.android.cdm.CDMData_1_0.java
de.imc.mirror.sdk.android.cdm.CDMData_2_0.java
de.imc.mirror.sdk.android.cdm.CreationInfo.java
de.imc.mirror.sdk.android.cdm.Reference.java
de.imc.mirror.sdk.android.cdm.References.java
de.imc.mirror.sdk.android.cdm.Summary.java
de.imc.mirror.sdk.android.data.ChannelsTable.java
de.imc.mirror.sdk.android.data.DataDB.java
de.imc.mirror.sdk.android.data.DataTable.java
de.imc.mirror.sdk.android.data.MembersTable.java
de.imc.mirror.sdk.android.data.SendTable.java
de.imc.mirror.sdk.android.data.SpacesTable.java
de.imc.mirror.sdk.android.exceptions.InvalidBuildException.java
de.imc.mirror.sdk.android.exceptions.RequestException.java
de.imc.mirror.sdk.android.filter.AndFilter.java
de.imc.mirror.sdk.android.filter.DataModelFilter.java
de.imc.mirror.sdk.android.filter.NamespaceFilter.java
de.imc.mirror.sdk.android.filter.OrFilter.java
de.imc.mirror.sdk.android.filter.PeriodFilter.java
de.imc.mirror.sdk.android.filter.PublisherFilter.java
de.imc.mirror.sdk.android.filter.ReferencesFilter.java
de.imc.mirror.sdk.android.packet.DeleteRequestIQ.java
de.imc.mirror.sdk.android.packet.DeleteResponseIQ.java
de.imc.mirror.sdk.android.packet.PersistenceServiceDeleteProvider.java
de.imc.mirror.sdk.android.packet.PersistenceServiceQueryProvider.java
de.imc.mirror.sdk.android.packet.QueryRequestIQ.java
de.imc.mirror.sdk.android.packet.QueryResponseIQ.java
de.imc.mirror.sdk.android.utils.DatatypeConverter.java
de.imc.mirror.sdk.android.utils.DateToXsdDatetimeFormatter.java
org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl.java
org.apache.xerces.jaxp.datatype.DurationImpl.java
org.apache.xerces.jaxp.datatype.SerializedDuration.java
org.apache.xerces.jaxp.datatype.SerializedXMLGregorianCalendar.java
org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl.java
org.apache.xerces.util.DatatypeMessageFormatter.java