/* Copyright 2014 Sven van der Meer <vdmeer.sven@mykolab.com>
 *
 * 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 de.vandermeer.execs.cf;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.commons.lang3.StringUtils;

/**
 * A class finder searching for all subclasses of a given class with jar and package filters.
 *
 * @author     Sven van der Meer <vdmeer.sven@mykolab.com>
 * @version    v0.4.0 build 170413 (13-Apr-17) for Java 1.8
 * @since      v0.0.6
 */
public class CF {

	/** A locator object for jars in the class path. */
	protected final CF_Locator locator;

	/** A list of errors that might have been collected during a search. */
	protected final List<Throwable> errors;

	/** A boolean indicating if the locator need to run again, should be true when filters are changed. */
	protected boolean needsReRun;

	/** List of processed artifacts. */
	protected final Set<String> processed;

	/** Array of (partial) class and package names that are permanently excluded from search. */
	public String[] excludedNames = new String[]{
			"java.",
			"javax.",
			"org.apache.",
			"ch.qos.",
			"org.codehaus.",
			"junit.",
			"org.antlr.",
			"org.stringtemplate.",
			"org.jboss.",
			"org.slf4j."
	};

	/**
	 * Returns a new class finder object.
	 */
	public CF(){
		this.locator = new CF_Locator();
		this.errors = new ArrayList<Throwable>();
		this.processed = new HashSet<>();
		this.clearFilters();
	}

	/**
	 * Clears all settings, except the filters, on the class finder.
	 * @return self to allow for chaining
	 */
	public CF clear(){
		this.errors.clear();
		this.processed.clear();
		return this;
	}

	/**
	 * Clears all filters on the class finder.
	 * @return self to allow for chaining
	 */
	public CF clearFilters(){
		this.setJarFilter(null);
		this.setPkgFilter(null);
		return this;
	}

	/**
	 * Sets a jar filter.
	 * @param jarFilter new filter, use null or empty list to not filter. The list will be copied locally.
	 * @return self to allow for chaining
	 */
	public CF setJarFilter(List<String> jarFilter){
		this.locator.setJarFilter(jarFilter);
		this.needsReRun = true;
		return this;
	}

	/**
	 * Sets a package filter.
	 * @param pkgFilter new package filter, set to null to not filter
	 * @return self to allow for chaining
	 */
	public CF setPkgFilter(String pkgFilter){
		this.locator.setPkgFilter(pkgFilter);
		this.needsReRun = true;
		return this;
	}

	/**
	 * Returns a list of errors collected during a search.
	 * The list will be reset by any new search.
	 * @return list of collected errors
	 */
	public List<Throwable> getLastErrors(){
		return this.errors;
	}

	/**
	 * Returns all subclasses found for the given class.
	 * @param clazz class to search for
	 * @return all found subclasses
	 */
	public Set<Class<?>> getSubclasses(Class<?> clazz){
		Set<Class<?>> ret = new HashSet<Class<?>>();
		Set<Class<?>> w = null;

		if(clazz!=null){
			this.clear();
			Map<URI, String> locations = this.locator.getCfLocations();
			for(Entry<URI, String> entry : locations.entrySet()){
				try{
					w = search(clazz, entry.getKey(), locations.get(entry.getKey()));
					if(w!=null && (w.size()>0)){
						ret.addAll(w);
					}
				}
				catch(MalformedURLException ex){}
			}
		}

		return ret;
	}

	/**
	 * Returns all subclasses found for the given fully qualified class name.
	 * @param fqcn fully qualified class name, e.g. package and class name
	 * @return all found subclasses
	 */
	public Set<Class<?>> getSubclasses(String fqcn){
		if(fqcn==null){
			return new HashSet<Class<?>>();
		}
		else if(StringUtils.startsWith(fqcn, ".") || StringUtils.endsWith(fqcn, ".")){
			return new HashSet<Class<?>>();
		}

		Class<?> clazz = null;
		try{
			clazz = Class.forName(fqcn);
		}
		catch(ClassNotFoundException ex){
			this.clear();
			this.errors.add(ex);
			return new HashSet<Class<?>>();
		}
		return getSubclasses(clazz);
	}

	/**
	 * Returns all known subclasses for a given class, location and package name
	 * @param clazz class to search for
	 * @param location a URL to look into
	 * @param packageName a package name
	 * @return all found subclasses in location, empty set of none found
	 * @throws MalformedURLException
	 */
	private final Set<Class<?>> search(Class<?> clazz, URI location, String packageName) throws MalformedURLException{
		if(clazz==null || location==null){
			return new HashSet<Class<?>>();
		}

		File directory = new File(location.toURL().getFile());
		if(directory.exists()){
			return this.searchDirectory(clazz, directory, location, packageName).keySet();
		}
		else{
			return this.searchJar(clazz, location).keySet();
		}
	}

	/**
	 * Returns all known subclasses found in a given directory.
	 * @param clazz class name to look for
	 * @param directory search directory
	 * @param location a URI location for return map
	 * @param packageName a package name to test against class name
	 * @return a map with found classes, empty if none found
	 */
	protected final Map<Class<?>, URI> searchDirectory(Class<?> clazz, File directory, URI location, String packageName){
		Map<Class<?>, URI> ret = new HashMap<>();

		String[] files = directory.list();
		for(int i=0; i<files.length; i++){
			if(files[i].endsWith(".class")){
				String classname = files[i].substring(0, files[i].length()-6);
				try{
					Class<?> c = Class.forName(packageName + "." + classname);
					if(clazz.isAssignableFrom(c) && !clazz.getName().equals(packageName + "." + classname)){
						ret.put(c, location);
					}
				}
				catch(Exception ex){
					errors.add(ex);
				}
			}
		}
		return ret;
	}

	/**
	 * Returns all known subclasses found in a given location
	 * @param clazz class name to look for
	 * @param location a URI location for return map
	 * @return a map with found classes, empty if none found
	 */
	protected final Map<Class<?>, URI> searchJar(Class<?> clazz, URI location){
		Map<Class<?>, URI> ret = new HashMap<>();

		try{
			JarURLConnection conn = (JarURLConnection)location.toURL().openConnection();
			JarFile jarFile = conn.getJarFile();

			for(Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements();){
				JarEntry entry = e.nextElement();
				String entryname = entry.getName();
				if(this.processed.contains(entryname)){
					continue;
				}
				this.processed.add(entryname);

				if(!entry.isDirectory() && entryname.endsWith(".class")){
					String classname = entryname.substring(0, entryname.length()-6);
					if(classname.startsWith("/")){
						classname = classname.substring(1);
					}
					classname = classname.replace('/','.');
					if(!StringUtils.startsWithAny(classname, this.excludedNames)){
						try{
							Class<?> c = Class.forName(classname);
							if(clazz.isAssignableFrom(c) && !clazz.getName().equals(classname)){
								ret.put(c, location);
							}
						}
						catch(Exception exception){
							errors.add(exception);
						}
						catch(Error error){
							errors.add(error);
						}
					}
				}
			}
		}
		catch(IOException ignore){
			errors.add(ignore);
		}

		return ret;
	}

}


package org.intellimate.izou.sdk.resource;

import org.intellimate.izou.identification.Identification;
import org.intellimate.izou.resource.ResourceModel;

import java.util.ArrayList;
import java.util.List;

/**
 * An Resource is an object which is used to pass data from one part of the application to another.
 * Note! This Object is immutable!
 */
public class Resource<T> implements ResourceModel<T> {
    private final String resourceID;
    private final Identification provider;
    private final Identification consumer;
    private final T resource;

    /**
     * creates a new Resource.
     * @param resourceID the ID of the Resource
     */
    public Resource(String resourceID) {
        this(resourceID, null, null, null);
    }

    /**
     * creates a new Resource.
     * @param resourceID the ID of the Resource
     * @param provider the Provider of the Resource
     */
    public Resource(String resourceID, Identification provider) {
        this(resourceID, provider, null, null);
    }

    /**
     * creates a new Resource.
     * @param resourceID the ID of the Resource
     * @param provider the Provider of the Resource
     * @param t the resource
     */
    public Resource(String resourceID, Identification provider, T t) {
        this(resourceID, provider, t, null);
    }

    /**
     * creates a new Resource.
     * @param resourceID the ID of the Resource
     * @param consumer the ID of the Consumer
     * @param t the resource
     */
    public Resource(String resourceID, T t, Identification consumer) {
        this(resourceID, null, t, consumer);
    }

    /**
     * creates a new Resource.
     * @param resourceID the ID of the Resource
     * @param provider the Provider of the Resource
     * @param consumer the ID of the Consumer
     */
    public Resource(String resourceID, Identification provider, Identification consumer) {
        this(resourceID, provider, null, consumer);
    }

    /**
     * creates a new Resource.
     * @param resourceID the ID of the Resource
     * @param provider the Provider of the Resource
     * @param t the resource
     * @param consumer the ID of the Consumer
     */
    public Resource(String resourceID, Identification provider, T t, Identification consumer) {
        this.resourceID = resourceID;
        this.provider = provider;
        this.resource = t;
        this.consumer = consumer;
    }

    /**
     * returns the associated Resource data if set.
     * This method is thread-safe.
     * @return null or resource data
     */
    @Override
    public T getResource() {
        return resource;
    }

    /**
     * sets the Resource data.
     *

     * Note! this Object is immutable!
     *

     * @param resource the data to set
     * @return the Resource
     */
    public Resource<T> setResource(T resource) {
        return new Resource<>(resourceID, provider, resource, consumer);
    }

    /**
     * returns the ID of the Resource.
     * This method is thread-safe.
     * @return a String containing the ID of the resource
     */
    @Override
    public String getResourceID() {
        return resourceID;
    }

    /**
     * returns the provider of the Resource.
     * This method is thread-safe.
     * @return an Identification describing the provider of the Resource or null if not set
     */
    @Override
    public Identification getProvider() {
        return provider;
    }

    /**
     * returns whether a provider is set
     * @return true if this resource has an provider, false if not
     */
    @Override
    public boolean hasProvider() {
        return provider != null;
    }

    /**
     * sets who should or has provided the Resource Object.
     *

     * Note! this Object is immutable!
     *

     * @param provider an Identification describing the provider of the Resource
     * @return the Resource
     */
    public Resource<T> setProvider(Identification provider) {
        return new Resource<>(resourceID, provider, resource, consumer);
    }

    /**
     * returns the consumer of the object (if set).
     * @return null or an Identification describing the consumer of the Resource
     */
    @Override
    public Identification getConsumer() {
        return consumer;
    }

    /**
     * sets who should or has consumed the Resource Object.
     *

     * Note! this Object is immutable!
     *

     * @param consumer an Identification describing the consumer of the Resource
     * @return new Resource
     */
    public Resource<T> setConsumer(Identification consumer) {
        return new Resource<>(resourceID, provider, resource, consumer);
    }

    /**
     * creates a list with this Element in it.
     * @return a list
     */
    public List<Resource> toList() {
        List<Resource> resourceList = new ArrayList<>();
        resourceList.add(this);
        return resourceList;
    }

    /**
     * An ID must always be unique.
     * A Class like Activator or OutputPlugin can just provide their .class.getCanonicalName()
     * If you have to implement this interface multiple times, just concatenate unique Strings to
     * .class.getCanonicalName()
     *
     * @return A String containing an ID
     */
    @Override
    public String getID() {
        return resourceID;
    }

    @Override
    public String toString() {
        return "Resource{" +
                "resourceID='" + resourceID + '\'' +
                ", provider=" + provider +
                ", consumer=" + consumer +
                ", resource=" + resource +
                '}';
    }
}


/*
 * Copyright 2010 Workplace Systems PLC (http://www.workplacesystems.com/).
 *
 * 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 com.workplacesystems.utilsj.collections;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Implementation of Map3 structure for mapping three-level keys onto values. As
 * for HashMap, methods are not synchronized, so clients should protect against
 * multi-threading if necessary.
 */
public class HashMap3<K1,K2,K3,V> implements Map3<K1,K2,K3,V>
{
    private HashMap<K1,Map2<K2,K3,V>> maps = new HashMap<K1,Map2<K2,K3,V>>();

    public void clear()
    {
        maps.clear();
    }

    public boolean containsKey(Object key1, Object key2, Object key3)
    {
        Map2<K2,K3,V> map2 = maps.get(key1);
        return map2 != null && map2.containsKey(key2, key3);
    }

    public boolean containsValue(Object value)
    {
        // check all inner maps for presence of value
        for ( Iterator<K1> keys1 = maps.keySet().iterator(); keys1.hasNext(); )
        {
            Map2<K2,K3,V> inner_map = maps.get(keys1.next());
            if (inner_map.containsValue(value))
                return true;
        }
        return false;
    }

    public V get(Object key1, Object key2, Object key3)
    {
        // ask key1 map for key2 value
        if (maps.containsKey(key1))
        {
            return maps.get(key1).get(key2, key3);
        }
        return null;
    }

    public Map2<K2,K3,V> getMap(Object key1)
    {
        return maps.get(key1);
    }

    public boolean isEmpty()
    {
        return maps.isEmpty();
    }

    public V put(K1 key1, K2 key2, K3 key3, V value)
    {
        // retrieve (create if necessary) inner map for key1
        Map2<K2,K3,V> inner_map = maps.get(key1);
        if (inner_map == null)
        {
            inner_map = new HashMap2<K2,K3,V>();
            maps.put(key1, inner_map);
        }

        // replace key2 value in inner map
        V old_value = inner_map.get(key2, key3);
        inner_map.put(key2, key3, value);
        return old_value;
    }

    public V remove(Object key1, Object key2, Object key3)
    {
        // retrieve inner map for key1
        Map2<K2,K3,V> inner_map = maps.get(key1);
        if (inner_map == null) return null;

        // remove key2 (and whole inner_map if it's now empty)
        V old_value = inner_map.remove(key2, key3);
        if (inner_map.isEmpty())
            maps.remove(key1);

        return old_value;
    }

    /**
     * Returns the accumulated size of all the bottom level maps.
     */
    public int size()
    {
        int result = 0;
        // sum over all inner maps
        for ( Iterator<K1> keys1 = maps.keySet().iterator(); keys1.hasNext(); )
        {
            Map2<K2,K3,V> inner_map = maps.get(keys1.next());
            result += inner_map.size();
        }
        return result;
    }

    public List<V> values()
    {
        List<V> result = new ArrayList<V>();
        // accumulate over all inner maps
        for ( Iterator<K1> keys1 = maps.keySet().iterator(); keys1.hasNext(); )
        {
            Map2<K2,K3,V> inner_map = maps.get(keys1.next());
            List<V> inner_values = inner_map.values();
            result.addAll(inner_values);
        }
        return result;
    }

    public Set<K1> key1Set()
    {
        return maps.keySet();
    }
}


package org.intellimate.izou.sdk.contentgenerator;

import org.intellimate.izou.events.EventModel;
import org.intellimate.izou.resource.ResourceModel;
import org.intellimate.izou.sdk.Context;
import org.intellimate.izou.sdk.resource.Resource;
import org.intellimate.izou.sdk.specification.ContentGeneratorModel;
import org.intellimate.izou.sdk.util.AddOnModule;
import org.intellimate.izou.sdk.util.ResourceCreator;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * The Task of an ContentGenerator is to generate a Resources-Object when a Event it subscribed to was fired.
 *

 *     When an Event this ContentGenerator subscribed to was fired, the ContentGeneratorManager will run the instance
 *     of it in a ThreadPool and generate(String eventID) will be called.
 *

 */
public abstract class ContentGenerator extends AddOnModule implements ContentGeneratorModel, ResourceCreator {

    /**
     * Creates a new content generator.
     *
     * @param id the id of the content generator
     * @param context the context of the addOn
     */
    public ContentGenerator(String id, Context context) {
        super(context, id);
    }

    /**
     * this method is called to register for what Events it wants to provide Resources.
     *

     * The Event has to be in the following format: It should contain only one Descriptor and and one Resource with the
     * ID "description", which contains an description of the Event.
     *

     * @return a List containing ID's for the Events
     */
    @Override
    public List<? extends EventModel<?>> announceEvents() {
        return getTriggeredEvents().stream()
                .map(EventListener::getEvent)
                .collect(Collectors.toList());
    }

    /**
     * This method is called to register what resources the object provides.
     * just pass a List of Resources without Data in it.
     *
     * @return a List containing the resources the object provides
     */
    @Override
    public List<? extends ResourceModel> announceResources() {
        return getTriggeredResources();
    }

    /**
     * this method is called when an object wants to get a Resource.
     *

     * Don't use the Resources provided as arguments, they are just the requests.
     * There is a timeout after 1 second.
     *

     * @param list a list of resources without data
     * @param optional     if an event caused the action, it gets passed. It can also be null.
     * @return a list of resources with data
     */
    @Override
    public List<ResourceModel> provideResource(List<? extends ResourceModel> list, Optional<EventModel> optional) {
        //TODO: check arguments and return type here! Missing ID etc. Fail fast!
        return new ArrayList<>(triggered(list, optional));
    }

    /**
     * this method is called when an object wants to get a Resource.
     *

     * Don't use the Resources provided as arguments, they are just the requests.
     * There is a timeout after 1 second.
     *

     * @param list a list of resources without data
     * @param optional     if an event caused the action, it gets passed. It can also be null.
     * @return a list of resources with data
     */
    public abstract List<? extends Resource> triggered(List<? extends ResourceModel> list, Optional<EventModel> optional);
}


/**
 *
 * Copyright 2003-2007 Jive Software.
 *
 * All rights reserved. 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.jivesoftware.smack;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

import org.jivesoftware.smack.filter.PacketFilter;
import org.xmpp.packet.Packet;

/**
 * Provides a mechanism to collect packets into a result queue that pass a
 * specified filter. The collector lets you perform blocking and polling
 * operations on the result queue. So, a PacketCollector is more suitable to use
 * than a {@link PacketListener} when you need to wait for a specific result.
 * <p>
 *
 * Each packet collector will queue up a configured number of packets for
 * processing before older packets are automatically dropped. The default number
 * is retrieved by {@link SmackConfiguration#getPacketCollectorSize()}.
 *
 * @see Connection#createPacketCollector(PacketFilter)
 * @author Matt Tucker
 */
public class PacketCollector {

    private PacketFilter packetFilter;
    private ArrayBlockingQueue<Packet> resultQueue;
    private Connection connection;
    private boolean cancelled = false;

    /**
     * Creates a new packet collector. If the packet filter is <tt>null</tt>,
     * then all packets will match this collector.
     *
     * @param conection
     *            the connection the collector is tied to.
     * @param packetFilter
     *            determines which packets will be returned by this collector.
     */
    protected PacketCollector(Connection conection, PacketFilter packetFilter) {
        this(conection, packetFilter, SmackConfiguration
                .getPacketCollectorSize());
    }

    /**
     * Creates a new packet collector. If the packet filter is <tt>null</tt>,
     * then all packets will match this collector.
     *
     * @param conection
     *            the connection the collector is tied to.
     * @param packetFilter
     *            determines which packets will be returned by this collector.
     * @param maxSize
     *            the maximum number of packets that will be stored in the
     *            collector.
     */
    protected PacketCollector(Connection conection, PacketFilter packetFilter,
            int maxSize) {
        this.connection = conection;
        this.packetFilter = packetFilter;
        this.resultQueue = new ArrayBlockingQueue<Packet>(maxSize);
    }

    /**
     * Explicitly cancels the packet collector so that no more results are
     * queued up. Once a packet collector has been cancelled, it cannot be
     * re-enabled. Instead, a new packet collector must be created.
     */
    public void cancel() {
        // If the packet collector has already been cancelled, do nothing.
        if (!cancelled) {
            cancelled = true;
            connection.removePacketCollector(this);
        }
    }

    /**
     * Returns the packet filter associated with this packet collector. The
     * packet filter is used to determine what packets are queued as results.
     *
     * @return the packet filter.
     */
    public PacketFilter getPacketFilter() {
        return packetFilter;
    }

    /**
     * Polls to see if a packet is currently available and returns it, or
     * immediately returns <tt>null</tt> if no packets are currently in the
     * result queue.
     *
     * @return the next packet result, or <tt>null</tt> if there are no more
     *         results.
     */
    public Packet pollResult() {
        return resultQueue.poll();
    }

    /**
     * Returns the next available packet. The method call will block (not
     * return) until a packet is available.
     *
     * @return the next available packet.
     */
    public Packet nextResult() {
        try {
            return resultQueue.take();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the next available packet. The method call will block (not
     * return) until a packet is available or the <tt>timeout</tt> has elapased.
     * If the timeout elapses without a result, <tt>null</tt> will be returned.
     *
     * @param timeout
     *            the amount of time to wait for the next packet (in
     *            milleseconds).
     * @return the next available packet.
     */
    public Packet nextResult(long timeout) {
        try {
            return resultQueue.poll(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Processes a packet to see if it meets the criteria for this packet
     * collector. If so, the packet is added to the result queue.
     *
     * @param packet
     *            the packet to process.
     */
    protected void processPacket(Packet packet) {
        if (packet == null) {
            return;
        }

        if (packetFilter == null || packetFilter.accept(packet)) {
            while (!resultQueue.offer(packet)) {
                // Since we know the queue is full, this poll should never
                // actually block.
                resultQueue.poll();
            }
        }
    }
}


/*
 * Copyright 2010 Workplace Systems PLC (http://www.workplacesystems.com/).
 *
 * 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 com.workplacesystems.utilsj.collections.decorators;

import com.workplacesystems.utilsj.Callback;
import com.workplacesystems.utilsj.collections.Filter;
import com.workplacesystems.utilsj.collections.FilterableCollection;
import com.workplacesystems.utilsj.collections.FilterableSet;
import com.workplacesystems.utilsj.collections.SyncUtils;

/**
 *
 * @author  Administrator
 */
public class SynchronizedFilterableSet<E> extends SynchronizedSet<E> implements FilterableSet<E> {
    /**
     * Factory method to create a synchronized map.
     *
     * @param map  the map to decorate, must not be null
     * @throws IllegalArgumentException if map is null
     */
    public static <E> FilterableSet<E> decorate(FilterableSet<E> set) {
        return new SynchronizedFilterableSet<E>(set);
    }

    /**
     * Constructor that wraps (not copies).
     *
     * @param map  the map to decorate, must not be null
     * @throws IllegalArgumentException if map is null
     */
    protected SynchronizedFilterableSet(FilterableSet<E> set) {
        super(set);
    }

    /**
     * Constructor that wraps (not copies).
     *
     * @param map  the map to decorate, must not be null
     * @param lock  the lock object to use, must not be null
     * @throws IllegalArgumentException if map is null
     */
    protected SynchronizedFilterableSet(FilterableSet<E> set, Object lock) {
        super(set, lock);
    }

    protected FilterableSet<E> getFilterableSet()
    {
        return (FilterableSet<E>) collection;
    }

    public FilterableCollection<E> filteredCollection(final Filter<? super E> filter) {
        return SyncUtils.synchronizeRead(lock, new Callback<FilterableCollection<E>>() {
            @Override
            protected void doAction() {
                FilterableCollection<E> _col = getFilterableSet().filteredCollection(filter);
                _return(new SynchronizedFilterableCollection<E>(_col, lock));
            }
        });
    }

}


package org.intellimate.izou.sdk.frameworks.music.resources;

import org.intellimate.izou.events.EventModel;
import org.intellimate.izou.identification.Identification;
import org.intellimate.izou.resource.ResourceModel;
import org.intellimate.izou.sdk.frameworks.music.player.Volume;
import org.intellimate.izou.sdk.resource.Resource;

import java.util.Optional;

/**
 * this resource is simply used hold the playlist, can be obtained via the resourceManager
 * @author LeanderK
 * @version 1.0
 */
public class VolumeResource extends Resource<Integer> {
    public static final String ID = "izou.music.resource.volume";

    /**
     * creates a new Resource.
     * This method is thread-safe.
     *
     * @param provider   the Provider of the Resource
     */
    public VolumeResource(Identification provider) {
        super(ID, provider);
    }

    /**
     * creates a new Resource.
     * This method is thread-safe.
     *
     * @param provider   the Provider of the Resource
     * @param volume     the resource
     */
    public VolumeResource(Identification provider, Volume volume) {
        super(ID, provider, volume.getVolume());
    }

    /**
     * creates a new Resource.
     * This method is thread-safe.
     *
     * @param provider   the Provider of the Resource
     * @param consumer   the ID of the Consumer
     */
    public VolumeResource(Identification provider, Identification consumer) {
        super(ID, provider, consumer);
    }

    /**
     * creates a new Resource.
     * This method is thread-safe.
     *
     * @param provider   the Provider of the Resource
     * @param volume     the resource
     * @param consumer   the ID of the Consumer
     */
    public VolumeResource(Identification provider, Volume volume, Identification consumer) {
        super(ID, provider, volume.getVolume(), consumer);
    }

    /**
     * gets the first Volume if found in the EventModel
     * @param eventModel the EventModel
     * @return return the optional Volume
     */
    public static Optional<Volume> getVolume(EventModel eventModel) {
        if (eventModel.getListResourceContainer().containsResourcesFromSource(ID)) {
            return eventModel
                    .getListResourceContainer()
                    .provideResource(ID)
                    .stream()
                    .map(ResourceModel::getResource)
                    .filter(ob -> ob instanceof Integer)
                    .map(ob -> (Integer) ob)
                    .findAny()
                    .flatMap(Volume::createVolume);

        } else {
            return Optional.empty();
        }
    }
}


/*
 * Copyright 2012 buddycloud
 *
 * 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.jamppa.component.utils;

import org.apache.log4j.Logger;
import org.xmpp.packet.IQ;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.PacketError.Condition;
import org.xmpp.packet.PacketError.Type;

public class XMPPUtils {

    /**
     * Logs the error and returns an IQ error response
     *
     * @param iq
     * @param errorMessage
     * @param logger
     * @return
     */
    public static IQ error(IQ iq, String errorMessage, Logger logger) {
        logger.error(errorMessage);
        return error(iq, errorMessage);
    }

    /**
     * Logs the error and returns an IQ error response
     *
     * @param iq
     * @param errorMessage
     * @param logger
     * @return
     */
    public static IQ error(IQ iq, String errorMessage) {
        return XMPPUtils.createErrorResponse(iq, errorMessage,
                Condition.bad_request, Type.modify);
    }

    /**
     * @param iq
     * @param errorMessage
     * @param logger
     * @return
     */
    public static IQ error(IQ iq, String errorMessage, Exception e,
            Logger logger) {
        logger.error(errorMessage, e);
        return XMPPUtils.createErrorResponse(iq, errorMessage,
                Condition.bad_request, Type.modify);
    }

    /**
     * Logs the RSM page not found error and returns an IQ error response
     *
     * @param iq
     * @param errorMessage
     * @param logger
     * @return
     */
    public static IQ errorRSM(IQ iq, Logger logger) {
        String rsmMessage = "RSM: Page Not Found";
        logger.error(rsmMessage + " " + iq);
        return XMPPUtils.createErrorResponse(iq, rsmMessage,
                Condition.item_not_found, Type.cancel);
    }

    /**
     * Creates an error response for a given IQ request.
     *
     * @param request
     * @param message
     * @param condition
     * @param type
     * @return
     */
    public static IQ createErrorResponse(final IQ request,
            final String message, Condition condition, Type type) {
        final IQ result = request.createCopy();
        result.setID(request.getID());
        result.setFrom(request.getTo());
        result.setTo(request.getFrom());

        PacketError e = new PacketError(condition, type);
        if (message != null) {
            e.setText(message);
        }
        result.setError(e);

        return result;
    }

}


package org.intellimate.izou.sdk.frameworks.common.resources;

import org.intellimate.izou.events.EventModel;
import org.intellimate.izou.identification.Identifiable;
import org.intellimate.izou.identification.Identification;
import org.intellimate.izou.resource.ResourceModel;
import org.intellimate.izou.sdk.resource.Resource;

import java.util.Collections;
import java.util.Optional;

/**
 * A resource which holds an Identification used for example to select the Player
 * @author LeanderK
 * @version 1.0
 */
public class SelectorResource extends Resource<Identification> {
    //also used in izou!
    public static final String RESOURCE_ID = "izou.common.resource.selector";

    /**
     * creates a new Resource.
     * This method is thread-safe.
     *
     * @param consumer   the Provider of the Resource
     */
    public SelectorResource(Identification consumer) {
        super(RESOURCE_ID, null, null, consumer);
    }

    /**
     * creates a new Resource.
     * This method is thread-safe.
     *
     * @param consumer       the consumer of the Resource
     * @param identification the resource
     */
    public SelectorResource(Identification consumer, Identification identification) {
        super(RESOURCE_ID, identification, identification, consumer);
    }

    /**
     * returns true if the identifiable is the target of the EventModel
     * @param eventModel the EventModel to check
     * @param identifiable the identifiable to check against
     * @return maybe true if found
     */
    public static Optional<Boolean> isTarget(EventModel eventModel, Identifiable identifiable) {
        if (eventModel.getListResourceContainer()
                .providesResource(Collections.singletonList(SelectorResource.RESOURCE_ID))) {
               return Optional.of(eventModel.getListResourceContainer()
                       .provideResource(SelectorResource.RESOURCE_ID)
                       .stream()
                       .map(ResourceModel::getResource)
                       .filter(resource -> resource instanceof Identification)
                       .map(object -> (Identification) object)
                       .anyMatch(identifiable::isOwner));
        } else {
            return Optional.empty();
        }
    }

    /**
     * returns true if the identifiable is the target of the EventModel
     * @param eventModel the EventModel to check
     * @param identification the identification to check against
     * @return maybe true if found
     */
    public static Optional<Boolean> isTarget(EventModel eventModel, Identification identification) {
        if (eventModel.getListResourceContainer()
                .providesResource(Collections.singletonList(SelectorResource.RESOURCE_ID))) {
            return Optional.of(eventModel.getListResourceContainer()
                    .provideResource(SelectorResource.RESOURCE_ID)
                    .stream()
                    .map(ResourceModel::getResource)
                    .filter(resource -> resource instanceof Identification)
                    .map(object -> (Identification) object)
                    .anyMatch(identification::equals));
        } else {
            return Optional.empty();
        }
    }
}


/*
 * Copyright 2010 Workplace Systems PLC (http://www.workplacesystems.com/).
 *
 * 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 com.workplacesystems.utilsj.collections.decorators;

import java.util.Comparator;
import java.util.SortedMap;
import com.workplacesystems.utilsj.Callback;
import com.workplacesystems.utilsj.collections.SyncUtils;

/**
 *
 * @author  Dave
 */
public class SynchronizedSortedMap<K,V> extends SynchronizedMap<K,V> implements SortedMap<K,V> {
    /**
     * Factory method to create a synchronized map.
     *
     * @param map  the map to decorate, must not be null
     * @throws IllegalArgumentException if map is null
     */
    public static <K,V> SortedMap<K,V> decorate(SortedMap<K,V> map) {
        return new SynchronizedSortedMap<K,V>(map);
    }

    /**
     * Constructor that wraps (not copies).
     *
     * @param map  the map to decorate, must not be null
     * @throws IllegalArgumentException if map is null
     */
    protected SynchronizedSortedMap(SortedMap<K,V> map) {
        super(map);
    }

    /**
     * Constructor that wraps (not copies).
     *
     * @param map  the map to decorate, must not be null
     * @param lock  the lock object to use, must not be null
     * @throws IllegalArgumentException if map is null
     */
    protected SynchronizedSortedMap(SortedMap<K,V> map, Object lock) {
        super(map, lock);
    }

    protected SortedMap<K,V> getSortedMap()
    {
        return (SortedMap<K,V>)map;
    }

    //-----------------------------------------------------------------------
    public Comparator<? super K> comparator() {
        return SyncUtils.synchronizeRead(lock, new Callback<Comparator<? super K>>() {
            @Override
            protected void doAction() {
                _return(getSortedMap().comparator());
            }
        });
    }

    public K firstKey() {
        return SyncUtils.synchronizeRead(lock, new Callback<K>() {
            @Override
            protected void doAction() {
                _return(getSortedMap().firstKey());
            }
        });
    }

    public SortedMap<K,V> headMap(final K toKey) {
        return SyncUtils.synchronizeRead(lock, new Callback<SortedMap<K,V>>() {
            @Override
            protected void doAction() {
                SortedMap<K,V> _map = getSortedMap().headMap(toKey);
                _return(new SynchronizedSortedMap<K,V>(_map, lock));
            }
        });
    }

    public K lastKey() {
        return SyncUtils.synchronizeRead(lock, new Callback<K>() {
            @Override
            protected void doAction() {
                _return(getSortedMap().lastKey());
            }
        });
    }

    public SortedMap<K,V> subMap(final K fromKey, final K toKey) {
        return SyncUtils.synchronizeRead(lock, new Callback<SortedMap<K,V>>() {
            @Override
            protected void doAction() {
                SortedMap<K,V> _map = getSortedMap().subMap(fromKey, toKey);
                _return(new SynchronizedSortedMap<K,V>(_map, lock));
            }
        });
    }

    public SortedMap<K,V> tailMap(final K fromKey) {
        return SyncUtils.synchronizeRead(lock, new Callback<SortedMap<K,V>>() {
            @Override
            protected void doAction() {
                SortedMap<K,V> _map = getSortedMap().tailMap(fromKey);
                _return(new SynchronizedSortedMap<K,V>(_map, lock));
            }
        });
    }
}


/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you 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.sakaiproject.nakamura.api.lite.authorizable;

import com.google.common.collect.ImmutableSet;

import org.apache.commons.lang.StringUtils;
import org.sakaiproject.nakamura.api.lite.Session;
import org.sakaiproject.nakamura.api.lite.StorageClientException;
import org.sakaiproject.nakamura.api.lite.accesscontrol.AccessDeniedException;
import org.sakaiproject.nakamura.api.lite.util.EnabledPeriod;

import java.security.Principal;
import java.util.Calendar;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import javax.security.auth.Subject;

/**
 * Representation of the User.
 */
public class User extends Authorizable {

    /**
     * The ID of the admin user.
     */
    public static final String ADMIN_USER = "admin";
    /**
     * The ID of the anon user.
     */
    public static final String ANON_USER = "anonymous";
    /**
     * The ID of the system user.
     */
    public static final String SYSTEM_USER = "system";
    public static final String IMPERSONATORS_FIELD = "impersonators";

    public User(Map<String, Object> userMap) throws StorageClientException, AccessDeniedException {
        this(userMap, null);
    }

    public User(Map<String, Object> userMap, Session session) throws StorageClientException,
            AccessDeniedException {
        super(userMap, session);
    }

    /**
     * @return true if this user is an administrative user.
     */
    public boolean isAdmin() {
        return SYSTEM_USER.equals(id) || ADMIN_USER.equals(id)
                || principals.contains(ADMINISTRATORS_GROUP);
    }

    /**
     * Does this user allow any of the principals identified in the subject to
     * impersonate it.
     *
     * @param impersSubject
     *            a subject containing principals to be tested
     * @return true if this user allows one or more of the subjects to
     *         impersonate it.
     */
    // TODO: Unit test
    public boolean allowImpersonate(Subject impersSubject) {

        String impersonators = (String) getProperty(IMPERSONATORS_FIELD);
        if (impersonators == null) {
            return false;
        }
        Set<String> impersonatorSet = ImmutableSet.copyOf(StringUtils.split(impersonators, ';'));
        for (Principal p : impersSubject.getPrincipals()) {

            if (ADMIN_USER.equals(p.getName()) || SYSTEM_USER.equals(p.getName())
                    || impersonatorSet.contains(p.getName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return returns true if login is enabled for this user.
     * @since 1.4
     */
    public boolean isLoginEnabled() {
        return EnabledPeriod.isInEnabledPeriod((String) getProperty(LOGIN_ENABLED_PERIOD_FIELD));
    }

    /**
     * Sets the login enabled time
     *
     * @param from
     *            UTC ms time after which user login is enabled. < 0 means no
     *            start time.
     * @param to
     *            UTC ms time before which the user login is enabled, < 0 means
     *            no end time.
     * @param day
     *            true if the time represents a day rather than a time
     * @param timeZone
     *            the timezone which both these times should be interpreted in
     *            (relevant for a day setting).
     * @since 1.4
     */
    public void setLoginEnabled(long from, long to, boolean day, TimeZone timeZone) {
        String enabledSetting = EnabledPeriod.getEnableValue(from, to, day, timeZone);
        if (enabledSetting == null) {
            removeProperty(LOGIN_ENABLED_PERIOD_FIELD);
        } else {
            setProperty(LOGIN_ENABLED_PERIOD_FIELD, enabledSetting);
        }
    }

    /**
     * @return an array length 2 of the times when the user is enabled in order
     *         from to. null indicates no time specified for either from or to
     *         times. This user will be allowed to login between those times.
     * @since 1.4
     */
    public Calendar[] getLoginEnabledPeriod() {
        return EnabledPeriod.getEnabledPeriod((String) getProperty(LOGIN_ENABLED_PERIOD_FIELD));
    }

}


/**
 *
 * Copyright 2003-2006 Jive Software.
 *
 * All rights reserved. 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.jivesoftware.smack.filter;

import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;

/**
 * A filter for IQ packet types. Returns true only if the packet is an IQ packet
 * and it matches the type provided in the constructor.
 *
 * @author Alexander Wenckus
 *
 */
public class IQTypeFilter implements PacketFilter {

    private IQ.Type type;

    public IQTypeFilter(IQ.Type type) {
        this.type = type;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * org.jivesoftware.smack.filter.PacketFilter#accept(org.jivesoftware.smack
     * .packet.Packet)
     */
    public boolean accept(Packet packet) {
        return (packet instanceof IQ && ((IQ) packet).getType().equals(type));
    }
}


/*
 * Copyright 2010 Workplace Systems PLC (http://www.workplacesystems.com/).
 *
 * 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 com.workplacesystems.utilsj.collections.decorators;

import java.util.Set;

/**
 * SynchronizedSet decorates another Set
 * to synchronize its behaviour for a multi-threaded environment.
 *

 * Methods are synchronized, then forwarded to the decorated set.
 *
 * @since Commons Collections 3.0
 * @version $Revision: 1.3 $ $Date: 2003/08/31 17:24:46 $
 *
 * @author Stephen Colebourne
 */
public class SynchronizedSet<E> extends SynchronizedCollection<E> implements Set<E> {

    /**
     * Factory method to create a synchronized set.
     *
     * @param set  the set to decorate, must not be null
     * @throws IllegalArgumentException if set is null
     */
    public static <E> Set<E> decorate(Set<E> set) {
        return new SynchronizedSet<E>(set);
    }

    /**
     * Constructor that wraps (not copies).
     *
     * @param set  the set to decorate, must not be null
     * @throws IllegalArgumentException if set is null
     */
    protected SynchronizedSet(Set<E> set) {
        super(set);
    }

    /**
     * Constructor that wraps (not copies).
     *
     * @param set  the set to decorate, must not be null
     * @param lock  the lock object to use, must not be null
     * @throws IllegalArgumentException if set is null
     */
    protected SynchronizedSet(Set<E> set, Object lock) {
        super(set, lock);
    }

    /**
     * Gets the decorated set.
     *
     * @return the decorated set
     */
    protected Set<E> getSet() {
        return (Set<E>) collection;
    }

}


/**
 *
 * Copyright 2003-2007 Jive Software.
 *
 * All rights reserved. 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.jivesoftware.smack;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Roster;
import org.xmpp.packet.Roster.Ask;
import org.xmpp.packet.Roster.Subscription;

/**
 * Each user in your roster is represented by a roster entry, which contains the
 * user's JID and a name or nickname you assign.
 *
 * @author Matt Tucker
 */
public class RosterEntry {

    private String user;
    private String name;
    private Subscription subscription;
    private Ask ask;
    final private UserRoster roster;
    final private Connection connection;

    /**
     * Creates a new roster entry.
     *
     * @param user
     *            the user.
     * @param name
     *            the nickname for the entry.
     * @param type
     *            the subscription type.
     * @param ask
     *            the subscription status (related to subscriptions pending to
     *            be approbed).
     * @param connection
     *            a connection to the XMPP server.
     */
    RosterEntry(String user, String name, Subscription subscription, Ask ask,
            UserRoster roster, Connection connection) {
        this.user = user;
        this.name = name;
        this.subscription = subscription;
        this.ask = ask;
        this.roster = roster;
        this.connection = connection;
    }

    /**
     * Returns the JID of the user associated with this entry.
     *
     * @return the user associated with this entry.
     */
    public String getUser() {
        return user;
    }

    /**
     * Returns the name associated with this entry.
     *
     * @return the name.
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the name associated with this entry.
     *
     * @param name
     *            the name.
     */
    public void setName(String name) {
        // Do nothing if the name hasn't changed.
        if (name != null && name.equals(this.name)) {
            return;
        }
        this.name = name;
        Roster packet = new Roster();
        packet.setType(IQ.Type.set);
        packet.addItem(new JID(user), name, ask, subscription, getGroupNames());
        connection.sendPacket(packet);
    }

    /**
     * Updates the state of the entry with the new values.
     *
     * @param name
     *            the nickname for the entry.
     * @param type
     *            the subscription type.
     * @param status
     *            the subscription status (related to subscriptions pending to
     *            be approbed).
     */
    void updateState(String name, Subscription type, Ask status) {
        this.name = name;
        this.subscription = type;
        this.ask = status;
    }

    /**
     * Returns an unmodifiable collection of the roster groups that this entry
     * belongs to.
     *
     * @return an iterator for the groups this entry belongs to.
     */
    public Collection<RosterGroup> getGroups() {
        List<RosterGroup> results = new ArrayList<RosterGroup>();
        // Loop through all roster groups and find the ones that contain this
        // entry. This algorithm should be fine
        for (RosterGroup group : roster.getGroups()) {
            if (group.contains(this)) {
                results.add(group);
            }
        }
        return Collections.unmodifiableCollection(results);
    }

    public List<String> getGroupNames() {
        List<String> results = new ArrayList<String>();
        // Loop through all roster groups and find the ones that contain this
        // entry. This algorithm should be fine
        for (RosterGroup group : roster.getGroups()) {
            if (group.contains(this)) {
                results.add(group.getName());
            }
        }
        return Collections.unmodifiableList(results);
    }

    /**
     * Returns the roster subscription type of the entry. When the type is
     * RosterPacket.ItemType.none or RosterPacket.ItemType.from, refer to
     * {@link RosterEntry getStatus()} to see if a subscription request is
     * pending.
     *
     * @return the type.
     */
    public Subscription getSubscription() {
        return subscription;
    }

    /**
     * Returns the roster subscription status of the entry. When the status is
     * RosterPacket.ItemStatus.SUBSCRIPTION_PENDING, the contact has to answer
     * the subscription request.
     *
     * @return the status.
     */
    public Ask getAsk() {
        return ask;
    }

    public String toString() {
        StringBuilder buf = new StringBuilder();
        if (name != null) {
            buf.append(name).append(": ");
        }
        buf.append(user);
        Collection<RosterGroup> groups = getGroups();
        if (!groups.isEmpty()) {
            buf.append(" [");
            Iterator<RosterGroup> iter = groups.iterator();
            RosterGroup group = iter.next();
            buf.append(group.getName());
            while (iter.hasNext()) {
                buf.append(", ");
                group = iter.next();
                buf.append(group.getName());
            }
            buf.append("]");
        }
        return buf.toString();
    }

    @Override
    public int hashCode() {
        return (user == null ? 0 : user.hashCode());
    }

    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (object != null && object instanceof RosterEntry) {
            return user.equals(((RosterEntry) object).getUser());
        } else {
            return false;
        }
    }

    /**
     * Indicates whether some other object is "equal to" this by comparing all
     * members.
     *

     * The {@link #equals(Object)} method returns true if the user
     * JIDs are equal.
     *
     * @param obj
     *            the reference object with which to compare.
     * @return true if this object is the same as the obj argument;
     *         false otherwise.
     */
    public boolean equalsDeep(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        RosterEntry other = (RosterEntry) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (ask == null) {
            if (other.ask != null)
                return false;
        } else if (!ask.equals(other.ask))
            return false;
        if (subscription == null) {
            if (other.subscription != null)
                return false;
        } else if (!subscription.equals(other.subscription))
            return false;
        if (user == null) {
            if (other.user != null)
                return false;
        } else if (!user.equals(other.user))
            return false;
        return true;
    }

}


/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you 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 uk.co.tfd.sm.memory.ehcache;

import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.sakaiproject.nakamura.api.memory.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 *
 */
public class CacheImpl<V> implements Cache<V> {

  private static final Logger LOGGER = LoggerFactory.getLogger(CacheImpl.class);
private String cacheName;
  private net.sf.ehcache.Cache cache;
  private long miss;
  private long hits;
  private long gets;

  /**
   * @param cacheManager
   * @param name
   */
  public CacheImpl(CacheManager cacheManager, String name) {
    if (name == null) {
      cacheName = "default";
    } else {
      cacheName = name;
    }
    synchronized (cacheManager) {
      cache = cacheManager.getCache(cacheName);
      if (cache == null) {
        cacheManager.addCache(cacheName);
        cache = cacheManager.getCache(cacheName);
        if (cache == null) {
          throw new RuntimeException("Failed to create Cache with name " + cacheName);
        }
      }
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see org.sakaiproject.nakamura.api.memory.Cache#clear()
   */
  public void clear() {
    cache.removeAll();
  }

  /**
   * {@inheritDoc}
   *
   * @see org.sakaiproject.nakamura.api.memory.Cache#containsKey(java.lang.String)
   */
  public boolean containsKey(String key) {
    return cache.isKeyInCache(key);
  }

  /**
   * {@inheritDoc}
   *
   * @see org.sakaiproject.nakamura.api.memory.Cache#get(java.lang.String)
   */
  public V get(String key) {
    Element e = cache.get(key);
    if (e == null) {
      return stats(null);
    }
    return stats(e.getObjectValue());
  }

  @SuppressWarnings("unchecked")
  private V stats(Object objectValue) {
	if ( objectValue == null ) {
		miss++;
	} else {
		hits++;
	}
	gets++;
	if ( gets % 1000 == 0 ) {
        long hp = (100*hits)/gets;
        long mp = (100*miss)/gets;
        LOGGER.info("{} Cache Stats hits {} ({}%), misses {} ({}%), calls {}",new Object[]{cacheName,hits,hp,miss,mp,gets});
	}
	return (V) objectValue;
  }

/**
   * {@inherit-doc}
   *
   * @see org.sakaiproject.nakamura.api.memory.Cache#put(java.lang.String, java.lang.Object)
   */
  @SuppressWarnings("unchecked")
  public V put(String key, V payload) {
    V previous = null;
    if (cache.isKeyInCache(key)) {
      Element e = cache.get(key);
      if (e != null) {
        previous = (V) e.getObjectValue();
      }
    }
    cache.put(new Element(key, payload));
    return previous;
  }

  /**
   * {@inherit-doc}
   *
   * @see org.sakaiproject.nakamura.api.memory.Cache#remove(java.lang.String)
   */
  public void remove(String key) {
    cache.remove(key);
  }

  /**
   * {@inheritDoc}
   *
   * @see org.sakaiproject.nakamura.api.memory.Cache#removeChildren(java.lang.String)
   */
  public void removeChildren(String key) {
    cache.remove(key);
    if (!key.endsWith("/")) {
      key = key + "/";
    }
    List<?> keys = cache.getKeys();
    for (Object k : keys) {
      if (((String) k).startsWith(key)) {
        cache.remove(k);
      }
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see org.sakaiproject.nakamura.api.memory.Cache#list()
   */
  @SuppressWarnings("unchecked")
  public List<V> list() {
    List<String> keys = cache.getKeys();
    List<V> values = new ArrayList<V>();
    for (String k : keys) {
      Element e = cache.get(k);
      if ( e != null ) {
        values.add((V) e.getObjectValue());
      }
    }
    return values;
  }

}


/*
 * Copyright 2012 buddycloud
 *
 * 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.jamppa.component.utils;

import java.util.LinkedList;
import java.util.List;

import org.dom4j.Element;
import org.jamppa.component.model.Identifiable;

/**
 * It is responsible for providing utility methods related to RSM format
 * (http://xmpp.org/extensions/xep-0059.html), which are used on the query
 * processing and response.
 *
 * @see RSM
 *
 */
public class RSMUtils {

    /**
     * Appends RSM info to query response.
     *
     * @param queryElement
     * @param rsm
     */
    public static void appendRSMElement(Element queryElement, RSM rsm) {
        Element setElement = queryElement.addElement("set", RSM.NAMESPACE);

        if (rsm.getFirst() != null) {
            Element firstElement = setElement.addElement("first");
            firstElement.addAttribute("index", rsm.getIndex().toString());
            firstElement.setText(rsm.getFirst());
        }

        if (rsm.getLast() != null) {
            Element lastElement = setElement.addElement("last");
            lastElement.setText(rsm.getLast());
        }

        setElement.addElement("count").setText(String.valueOf(rsm.getCount()));
    }

    /**
     * Parses an RSM from a query XML element
     *
     * @param queryElement
     * @return The parsed RSM object
     */
    public static RSM parseRSM(Element queryElement) {
        RSM rsm = new RSM();

        Element setElement = queryElement.element("set");
        if (setElement == null) {
            return rsm;
        }

        Element after = setElement.element("after");
        if (after != null) {
            rsm.setAfter(after.getText());
        }

        Element before = setElement.element("before");
        if (before != null) {
            String beforeText = before.getText();
            rsm.setBefore(beforeText == null ? "" : beforeText);
        }

        Element index = setElement.element("index");
        if (index != null) {
            rsm.setIndex(Integer.parseInt(index.getText()));
        }

        Element max = setElement.element("max");
        if (max != null) {
            rsm.setMax(Integer.parseInt(max.getText()));
        }

        return rsm;
    }

    /**
     * Filters response objects based on the RSM parameters. Updates the RSM
     * object with item count, first and last jid
     *
     * @param objects
     * @param rsm
     * @return
     * @throws IllegalArgumentException
     *             If the item specified by the requesting entity via the UID in
     *             the <after/> or <before/> element does not exist
     */
    public static List<Identifiable> filterRSMResponse(
            List<Identifiable> objects, RSM rsm)
            throws IllegalArgumentException {

        String after = rsm.getAfter();
        String before = rsm.getBefore();

        int initialIndex = rsm.getIndex();
        int lastIndex = objects.size();

        if (after != null || (before != null && !before.isEmpty())) {

            boolean afterItemFound = false;
            boolean beforeItemFound = false;

            int i = 0;
            for (Identifiable object : objects) {
                if (after != null && after.equals(object.getId())) {
                    initialIndex = i + 1;
                    afterItemFound = true;
                }
                if (before != null && before.equals(object.getId())) {
                    lastIndex = i;
                    beforeItemFound = true;
                }
                i++;
            }

            if (after != null && !afterItemFound) {
                throw new IllegalArgumentException();
            }

            if (before != null && !before.isEmpty() && !beforeItemFound) {
                throw new IllegalArgumentException();
            }
        }

        if (rsm.getMax() != null) {
            if (before != null) {
                initialIndex = lastIndex - rsm.getMax();
            } else {
                lastIndex = initialIndex + rsm.getMax();
            }
        }

        boolean outOfRange = initialIndex > lastIndex || initialIndex < 0
                || lastIndex > objects.size();

        List<Identifiable> filteredList = outOfRange ? new LinkedList<Identifiable>()
                : objects.subList(initialIndex, lastIndex);

        rsm.setCount(objects.size());
        rsm.setIndex(initialIndex);

        if (!filteredList.isEmpty()) {
            rsm.setFirst(filteredList.get(0).getId());
            rsm.setLast(filteredList.get(filteredList.size() - 1).getId());
        }

        return filteredList;
    }

}


package uk.co.tfd.sm.search.es;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.action.bulk.BulkRequestBuilder;
import org.elasticsearch.client.action.index.IndexRequestBuilder;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.inject.CreationException;
import org.elasticsearch.common.inject.spi.Message;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.ImmutableSettings.Builder;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeBuilder;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.sakaiproject.nakamura.api.lite.ClientPoolException;
import org.sakaiproject.nakamura.api.lite.Repository;
import org.sakaiproject.nakamura.api.lite.Session;
import org.sakaiproject.nakamura.api.lite.StorageClientException;
import org.sakaiproject.nakamura.api.lite.accesscontrol.AccessDeniedException;
import org.sakaiproject.nakamura.api.lite.util.Iterables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import uk.co.tfd.sm.api.search.IndexingHandler;
import uk.co.tfd.sm.api.search.InputDocument;
import uk.co.tfd.sm.api.search.RepositorySession;
import uk.co.tfd.sm.api.search.TopicIndexer;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * Indexes content using elastic search. Driven by Events expected to be
 * synchronous inside transactions.
 *
 * @author ieb
 *
 */
@Component(immediate = true, metatype = true)
@Service(value = { EventHandler.class, TopicIndexer.class })
public class ContentEventListener implements EventHandler, TopicIndexer {

	@Property(value = { "org/sakaiproject/nakamura/lite/*" }, propertyPrivate = true)
	static final String TOPICS = EventConstants.EVENT_TOPIC;

	private static final String[] DEFAULT_ESCLUSTER = { "host1:port",
			"host2:port" };

	@Property(value = { "host1:port", "host2:port" })
	private static final String PROP_ESCLUSTER = "ec-cluster-hosts";

	@Property(boolValue = true, description = "If set to true, the ES node is embedded and joins the cluster")
	private static final String PROP_EMBEDED = "embeded";

	private static final String DEFAULT_CLUSTER_NAME = "smc-cluster";

	@Property(value = DEFAULT_CLUSTER_NAME, description = "Name of the elsastic search cluster to join when embedded")
	private static final String PROP_CLUSTER_NAME = "clustername";

	@Property(boolValue = true, description = "If set to true, the ES node should serve local shards")
	private static final String PROP_LOCAL_SHARDS = "local-shards";

	private static final Logger LOGGER = LoggerFactory
			.getLogger(ContentEventListener.class);

	private Map<String, Collection<IndexingHandler>> handlers = Maps
			.newConcurrentMap();

	/**
	 * A protective lock surrounding adding and removing keys from the handlers
	 * map. THis is there because we could have 2 threads adding to the same key
	 * at the same time. Its not there to protect the map itself or access to
	 * iterators on the objects in the map as those changes are still atomic.
	 * see usage for detail.
	 */
	private Object handlersLock = new Object();

	private Client client;

	private Node node;

	@Reference
	private Repository repository;

	@Activate
	protected void activate(Map<String, Object> properties) throws IOException,
			ClientPoolException, StorageClientException, AccessDeniedException {
		try {
			Boolean embeded = Utils.get(properties.get(PROP_EMBEDED), true);
			Boolean withData = Utils.get(properties.get(PROP_LOCAL_SHARDS), true);
			String clusterName = Utils.get(properties.get(PROP_CLUSTER_NAME),
					DEFAULT_CLUSTER_NAME);
			if (client == null) {
				LOGGER.error("Thread context classloader is {} ", Thread.currentThread().getContextClassLoader());
				// Elastic search needs to come up this class so unfortunately we have to set the context classloader
				// as it will use that by default
				Thread thisThread = Thread.currentThread();
				ClassLoader classloader = thisThread.getContextClassLoader();
				try {
					thisThread.setContextClassLoader(this.getClass().getClassLoader());
					if (embeded) {
						node = NodeBuilder.nodeBuilder().data(withData)
								.clusterName(clusterName).build();
						client = node.client();
					} else {
						Builder settingsBuilder = ImmutableSettings.settingsBuilder();
						settingsBuilder.put("cluster.name", clusterName);
						TransportClient tclient = new TransportClient(
								settingsBuilder.build());
						String[] clusterHosts = Utils.get(
								properties.get(PROP_ESCLUSTER), DEFAULT_ESCLUSTER);
						for (String s : clusterHosts) {
							String[] h = StringUtils.split(s, ":");
							tclient.addTransportAddress(new InetSocketTransportAddress(
									h[0], Integer.parseInt(h[1])));
						}
						client = tclient;
					}
				} finally {
					thisThread.setContextClassLoader(classloader);
				}
			}
		} catch ( Exception e ) {
			LOGGER.error("Failed to start Elastic search {} ",e.getClass());
			for ( StackTraceElement se : e.getStackTrace()) {
				LOGGER.error("Error {} {} {} {} ", new Object[]{se.getClassName(), se.getFileName(), se.getLineNumber(), se.getMethodName()});
			}
			Throwable c = e.getCause();
			while (c != null) {
				LOGGER.error("Caused By : {} ",e.getClass());
				for ( StackTraceElement se : c.getStackTrace()) {
					LOGGER.error("Error {} {} {} {} ", new Object[]{se.getClassName(), se.getFileName(), se.getLineNumber(), se.getMethodName()});
				}
			}
			LOGGER.error("End of cause ");
			if ( e instanceof CreationException ) {
				CreationException ce = (CreationException) e;
				for ( Message m : ce.getErrorMessages()) {
					LOGGER.error("Error message {} ",m.getMessage());
				}
				LOGGER.error(e.getMessage());
			}
			throw new RuntimeException(e);
		}

	}

	@Deactivate
	protected void deactivate(Map<String, Object> properties)
			throws IOException {
		if (client != null) {
			client.close();
			client = null;
		}
		if (node != null) {
			node.close();
			node = null;
		}
	}

	/**
	 * Handles an event from OSGi and indexes it. The indexing operation should
	 * only index metadata and not bodies. Indexing of bodies is performed by a
	 * seperate thread.
	 *
	 * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
	 */
	public void handleEvent(Event event) {
		String topic = event.getTopic();
		Session session = (Session) event.getProperty(Session.class.getName());
		RepositorySession repositoryRession = null;
		Thread thisThread = Thread.currentThread();
		ClassLoader classloader = thisThread.getContextClassLoader();
		// ES might load classes so we had better set the context classloader.
		try {
			thisThread.setContextClassLoader(this.getClass().getClassLoader());
			try {
				repositoryRession = new RepositorySessionImpl(session,
						repository);
			} catch (ClientPoolException e1) {
				LOGGER.error(e1.getMessage(), e1);
				return;
			} catch (StorageClientException e1) {
				LOGGER.error(e1.getMessage(), e1);
				return;
			} catch (AccessDeniedException e1) {
				LOGGER.error(e1.getMessage(), e1);
				return;
			}

			LOGGER.debug("Got Event {} {} ", event, handlers);
			Collection<IndexingHandler> contentIndexHandler = handlers
					.get(topic);
			if (contentIndexHandler != null && contentIndexHandler.size() > 0) {
				BulkRequestBuilder bulk = client.prepareBulk();
				int added = 0;
				for (IndexingHandler indexingHandler : contentIndexHandler) {
					Collection<InputDocument> documents = indexingHandler
							.getDocuments(repositoryRession, event);
					for (InputDocument in : documents) {
						LOGGER.info("Indexing {} ", in);
						if (in.isDelete()) {
							bulk.add(client.prepareDelete(in.getIndexName(),
									in.getDocumentType(), in.getDocumentId()));
							added++;
						} else {
							try {
								IndexRequestBuilder r = client.prepareIndex(
										in.getIndexName(),
										in.getDocumentType(),
										in.getDocumentId());
								XContentBuilder d = XContentFactory
										.jsonBuilder();
								d = d.startObject();
								for (Entry<String, Object> e : in.getKeyData()) {
									d = d.field(e.getKey(), e.getValue());
								}
								r.setSource(d.endObject());
								bulk.add(r);
								added++;
							} catch (IOException e) {
								LOGGER.error(e.getMessage(), e);
							}
						}
					}
				}
				if ( added > 0 ) {
					BulkResponse resp = bulk.execute().actionGet();
					if (resp.hasFailures()) {
						for (BulkItemResponse br : Iterables.adaptTo(resp
								.iterator())) {
							if (br.failed()) {
								LOGGER.error("Failed {} {} ", br.getId(),
										br.getFailureMessage());
								// not going to retry at the moment, just log.
							}
						}
					}
				}

			}
		} finally {
			if (repositoryRession != null) {
				repositoryRession.logout();
			}
			thisThread.setContextClassLoader(classloader);
		}
	}

	public void addHandler(String topic, IndexingHandler handler) {
		synchronized (handlersLock) {
			Collection<IndexingHandler> topicHandlers = handlers.get(topic);
			if (topicHandlers == null) {
				topicHandlers = Sets.newHashSet();
			} else {
				// make a copy to avoid concurrency issues in the topicHandler
				topicHandlers = Sets.newHashSet(topicHandlers);
			}
			topicHandlers.add(handler);
			handlers.put(topic, topicHandlers);
		}
	}

	public void removeHandler(String topic, IndexingHandler handler) {
		synchronized (handlersLock) {
			Collection<IndexingHandler> topicHandlers = handlers.get(topic);
			if (topicHandlers != null && topicHandlers.size() > 0) {
				topicHandlers = Sets.newHashSet(topicHandlers);
				topicHandlers.remove(handler);
				handlers.put(topic, topicHandlers);
			}
		}
	}

}


package org.intellimate.izou.sdk.frameworks.presence.events;

import org.intellimate.izou.identification.Identification;
import org.intellimate.izou.sdk.events.CommonEvents;
import org.intellimate.izou.sdk.events.Event;

import java.util.List;
import java.util.Optional;

/**
 * this event guarantees that the user is not around anymore (as much as possible).
 * @author LeanderK
 * @version 1.0
 */
public class LeavingEvent extends Event {
    /**
     * this event does not mean the user is able to notice anything (can be used for warm-up), it indicates
     * he might be
     */
    public static final String GENERAL_DESCRIPTOR = "izou.presence.general.leaving";
    /**
     * it means that the addon can guarantee that the user left an area near izou
     */
    public static final String STRICT_DESCRIPTOR = "izou.presence.strict.leaving";
    /**
     * it means that the addon can guarantee that the user entered an area near izou
     */
    public static final String ID = "izou.leaving";

    /**
     * Creates a new Event Object
     *
     * @param source      the source of the Event, most likely a this reference.
     * @param descriptors the descriptors to initialize the Event with
     * @throws IllegalArgumentException if one of the Arguments is null or empty
     */
    protected LeavingEvent(Identification source, List<String> descriptors) throws IllegalArgumentException {
        super(CommonEvents.Type.RESPONSE_TYPE, source, descriptors);
    }

    /**
     * creates a new LeavingEvent
     * @param source the caller
     * @param strict whether the addon can guarantee that the user is around
     * @param descriptors the descriptors
     * @return the optional PresenceEvent
     */
    public static Optional<LeavingEvent> createLeavingEvent(Identification source, boolean strict, List<String> descriptors) {
        try {
            if (strict) {
                descriptors.add(STRICT_DESCRIPTOR);
            } else {
                descriptors.add(GENERAL_DESCRIPTOR);
            }
            descriptors.add(ID);
            descriptors.add(CommonEvents.Descriptors.NOT_INTERRUPT);
            LeavingEvent stopRequest = new LeavingEvent(source, descriptors);
            return Optional.of(stopRequest);
        } catch (IllegalArgumentException e) {
            return Optional.empty();
        }
    }
}