/**
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   This file is part of the LDP4j Project:
 *     http://www.ldp4j.org/
 *
 *   Center for Open Middleware
 *     http://www.centeropenmiddleware.com/
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Copyright (C) 2014-2016 Center for Open Middleware.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   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.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Artifact    : org.ldp4j.framework:ldp4j-application-engine-sdk:0.2.2
 *   Bundle      : ldp4j-application-engine-sdk-0.2.2.jar
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 */
package org.ldp4j.application.sdk.internal;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import org.ldp4j.application.sdk.spi.ObjectFactory;
import org.ldp4j.application.sdk.spi.ObjectParseException;

public final class PrimitiveObjectFactory<T> implements ObjectFactory<T> {

	private static final String FALSE = "false";
	private static final String TRUE = "true";

	private final Class<? extends T> valueClass;

	private PrimitiveObjectFactory(final Class<? extends T> valueClass) {
		this.valueClass = valueClass;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Class<? extends T> targetClass() {
		return this.valueClass;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	@SuppressWarnings("unchecked")
	public T fromString(final String rawValue) { // NOSONAR
		try {
			Object result = null;
			if (byte.class.equals(this.valueClass)) {
				result = Byte.decode(rawValue);
			} else if (short.class.equals(this.valueClass)) {
				result = Short.decode(rawValue);
			} else if (int.class.equals(this.valueClass)) {
				result = Integer.decode(rawValue);
			} else if (long.class.equals(this.valueClass)) {
				result = Long.decode(rawValue);
			} else if (double.class.equals(this.valueClass)) {
				result = Double.valueOf(rawValue);
			} else if (float.class.equals(this.valueClass)) {
				result = Float.valueOf(rawValue);
			} else if (boolean.class.equals(this.valueClass)) {
				result = parseBoolean(rawValue);
			} else { // Must be char
				result = parseCharacter(rawValue);
			}
			return (T) result;
		} catch (final Exception e) {
			throw new ObjectParseException(e, this.valueClass, rawValue);
		}
	}

	static Character parseCharacter(final String rawValue) {
		if (rawValue.length() != 1) {
			throw new IllegalArgumentException("Raw value has more than one character");
		}
		return Character.valueOf(rawValue.charAt(0));
	}

	static boolean parseBoolean(final String rawValue) {
		if (TRUE.equalsIgnoreCase(rawValue)) {
			return true;
		} else if (FALSE.equalsIgnoreCase(rawValue)) {
			return false;
		}
		throw new IllegalArgumentException("Not a standard boolean representation");
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString(final T value) {
		return value.toString();
	}

	/**
	 * Create a primitive object factory for the specified primitive class
	 *
	 * @param <T>
	 *            the primitive class type
	 * @param valueClass
	 *            the primitive class to use
	 * @return an object factory
	 * @throws NullPointerException
	 *             if the specified class is {@code null}
	 * @throws IllegalArgumentException
	 *             if the specified class is not a primitive class
	 */
	public static <T> PrimitiveObjectFactory<T> create(final Class<? extends T> valueClass) {
		checkNotNull(valueClass, "Value class cannot be null");
		checkArgument(valueClass.isPrimitive(), "Value class '" + valueClass.getName() + "' is not primitive");
		return new PrimitiveObjectFactory<T>(valueClass);
	}
}


/**
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   This file is part of the LDP4j Project:
 *     http://www.ldp4j.org/
 *
 *   Center for Open Middleware
 *     http://www.centeropenmiddleware.com/
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Copyright (C) 2014-2016 Center for Open Middleware.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   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.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Artifact    : org.ldp4j.framework:ldp4j-server-core:0.2.2
 *   Bundle      : ldp4j-server-core-0.2.2.jar
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 */
package org.ldp4j.server.utils;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Variant;

import org.ldp4j.server.data.DataTransformator;

public final class VariantUtils {

	private static final String[] TEMPLATES={
		"Media type: %1$s; encoding=%2$s; language=%3$s",
		"Media type: %1$s; language=%3$s",
	};

	private VariantUtils() {
	}

	public static List<Variant> defaultVariants() {
		return
			VariantUtils.
				createVariants(
					DataTransformator.supportedMediaTypes());
	}

	/**
	 * Get a list of acceptable variants. Current implementation only leverages
	 * media type for the specification of variants.
	 *
	 * @param mediaTypes
	 *            The list of acceptable media types.
	 * @return A list of acceptable variants.
	 */
	public static List<Variant> createVariants(MediaType... mediaTypes) {
		return
			Variant.VariantListBuilder.
				newInstance().
					mediaTypes(mediaTypes).
					encodings().
					languages().
					add().
					build();
	}

	public static List<Variant> createVariants(Collection<? extends MediaType> mediaTypes) {
		return createVariants(mediaTypes.toArray(new MediaType[mediaTypes.size()]));
	}

	public static String toString(Variant v) {
		return
			String.format(
				getTemplate(v),
				getMediaType(v),
				getEncoding(v),
				getLanguage(v));
	}

	public static String toString(List<Variant> variants) {
		StringBuilder builder=new StringBuilder();
		for(Iterator<Variant> it=variants.iterator();it.hasNext();) {
			String formatedVariants = toString(it.next());
			builder.append(formatedVariants);
			if(it.hasNext()) {
				builder.append(", ");
			}
		}
		return builder.toString();
	}

	private static String getTemplate(Variant v) {
		return
			v.getEncoding()!=null?
				TEMPLATES[0]:
				TEMPLATES[1];
	}

	private static String getLanguage(Variant v) {
		String language="*";
		Locale locale = v.getLanguage();
		if(locale!=null) {
			language=locale.toString();
		}
		return language;
	}

	private static String getEncoding(Variant v) {
		String encoding = v.getEncoding();
		if(encoding==null) {
			encoding="*";
		}
		return encoding;
	}

	private static MediaType getMediaType(Variant v) {
		MediaType mediaType = v.getMediaType();
		if(mediaType==null) {
			mediaType=new MediaType(MediaType.MEDIA_TYPE_WILDCARD,MediaType.MEDIA_TYPE_WILDCARD);
		}
		return mediaType;
	}

}


/**
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   This file is part of the LDP4j Project:
 *     http://www.ldp4j.org/
 *
 *   Center for Open Middleware
 *     http://www.centeropenmiddleware.com/
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Copyright (C) 2014-2016 Center for Open Middleware.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   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.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Artifact    : org.ldp4j.framework:ldp4j-application-data:0.2.2
 *   Bundle      : ldp4j-application-data-0.2.2.jar
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 */
package org.ldp4j.application.data;

import java.io.Serializable;
import java.net.URI;

public abstract class IndividualReference<T extends Serializable, S extends Individual<T,S>> {

	public static class ManagedIndividualReference extends IndividualReference<ManagedIndividualId,ManagedIndividual> {

		private ManagedIndividualReference(ManagedIndividualId resourceId) {
			super(resourceId,ManagedIndividual.class);
		}

		@Override
		public void accept(IndividualReferenceVisitor visitor) {
			visitor.visitManagedIndividualReference(this);
		}

	}

	public static class RelativeIndividualReference extends IndividualReference<RelativeIndividualId,RelativeIndividual> {

		private RelativeIndividualReference(RelativeIndividualId resourceId) {
			super(resourceId,RelativeIndividual.class);
		}

		@Override
		public void accept(IndividualReferenceVisitor visitor) {
			visitor.visitRelativeIndividualReference(this);
		}

	}

	@SuppressWarnings("rawtypes")
	public static final class LocalIndividualReference extends IndividualReference<Name,LocalIndividual> {

		private LocalIndividualReference(Name<?> name) {
			super(name,LocalIndividual.class);
		}

		@Override
		public void accept(IndividualReferenceVisitor visitor) {
			visitor.visitLocalIndividualReference(this);
		}

	}

	public static final class ExternalIndividualReference extends IndividualReference<URI,ExternalIndividual> {

		private ExternalIndividualReference(URI location) {
			super(location,ExternalIndividual.class);
		}

		@Override
		public void accept(IndividualReferenceVisitor visitor) {
			visitor.visitExternalIndividualReference(this);
		}

	}

	public static final class NewIndividualReference extends IndividualReference<URI,NewIndividual> {

		private NewIndividualReference(URI location) {
			super(location,NewIndividual.class);
		}

		@Override
		public void accept(IndividualReferenceVisitor visitor) {
			visitor.visitNewIndividualReference(this);
		}

	}

	private static final class ReferenceBuilder implements IndividualVisitor {
		private IndividualReference<?,?> result=null;

		private ReferenceBuilder() {
		}

		private IndividualReference<?,?> builtReference() {
			return this.result;
		}
		@Override
		public void visitManagedIndividual(ManagedIndividual individual) {
			this.result=IndividualReference.managed(individual.id());
		}
		@Override
		public void visitLocalIndividual(LocalIndividual individual) {
			this.result=IndividualReference.anonymous(individual.id());
		}
		@Override
		public void visitExternalIndividual(ExternalIndividual individual) {
			this.result=IndividualReference.external(individual.id());
		}
		@Override
		public void visitRelativeIndividual(RelativeIndividual individual) {
			this.result=IndividualReference.relative(individual.id());
		}
		@Override
		public void visitNewIndividual(NewIndividual individual) {
			this.result=IndividualReference.newIndividual(individual.id());
		}
	}

	private final T id;
	private final Class<? extends S> clazz;

	private IndividualReference(T id, Class<? extends S> clazz) {
		this.id = id;
		this.clazz = clazz;
	}

	public T ref() {
		return id;
	}

	public boolean isPresent(DataSet dataSet) {
		return dataSet.hasIndividual(ref());
	}

	/**
	 * Find the individual of the data set with the same identifier
	 *
	 * @param dataSet
	 *            the data set
	 * @return the individual with the same identifier, or {@code null} if no
	 *         individual has the same identifier.
	 */
	@SuppressWarnings("unchecked")
	public Individual<T,S> resolve(DataSet dataSet) {
		return (Individual<T,S>) dataSet.individualOfId(ref());
	}

	public Individual<T,S> realize(DataSet dataSet) {
		return dataSet.individual(ref(),clazz);
	}

	abstract void accept(IndividualReferenceVisitor visitor);

	@SuppressWarnings("rawtypes")
	public static IndividualReference<Name,LocalIndividual> anonymous(Name<?> name) {
		return new LocalIndividualReference(name);
	}

	public static IndividualReference<ManagedIndividualId,ManagedIndividual> managed(ManagedIndividualId individualId) {
		return new ManagedIndividualReference(individualId);
	}

	public static IndividualReference<ManagedIndividualId,ManagedIndividual> managed(Name<?> name, String templateId) {
		return managed(ManagedIndividualId.createId(name, templateId));
	}

	public static IndividualReference<ManagedIndividualId,ManagedIndividual> managed(Name<?> name, String templateId, URI indirectId) {
		return managed(indirectId,ManagedIndividualId.createId(name, templateId));
	}

	public static IndividualReference<ManagedIndividualId,ManagedIndividual> managed(URI indirectId, ManagedIndividualId parent) {
		return managed(ManagedIndividualId.createId(indirectId, parent));
	}

	public static IndividualReference<RelativeIndividualId,RelativeIndividual> relative(ManagedIndividualId parentId, URI path) {
		return relative(RelativeIndividualId.createId(parentId,path));
	}

	public static IndividualReference<RelativeIndividualId,RelativeIndividual> relative(RelativeIndividualId individualId) {
		return new RelativeIndividualReference(individualId);
	}

	public static IndividualReference<URI,ExternalIndividual> external(URI location) {
		return new ExternalIndividualReference(location);
	}

	public static IndividualReference<URI,NewIndividual> newIndividual(URI location) {
		return new NewIndividualReference(location);
	}

	@SuppressWarnings("unchecked")
	public static <T extends Serializable,S extends Individual<T,S>> IndividualReference<T,S> fromIndividual(Individual<T,S> value) {
		ReferenceBuilder builder = new ReferenceBuilder();
		value.accept(builder);
		return (IndividualReference<T, S>)builder.builtReference();
	}
}


/*
 * Copyright 2010 akquinet
 * 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.akquinet.android.marvin.monitor;

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.content.IntentFilter;
import android.util.Log;

public class ExtendedActivityMonitor
{
    private static final int CHECK_FOR_INTERRUPT_CYCLE_DURATION = 10000;

    private volatile boolean stopped = false;

    private Thread activityMonitorThread;
    private ActivityMonitor activityInstanceMonitor;

    /** holds all activity instances started during run of this monitor. */
    private List<StartedActivity> startedActivities =
            new LinkedList<StartedActivity>();

    /** holds listeners to be informed of certain activity starts */
    private Map<Class<? extends Activity>, List<ActivityStartListener>> activityStartListeners =
            new HashMap<Class<? extends Activity>, List<ActivityStartListener>>();

    public interface ActivityStartListener
    {
        void started(Activity activity);
    }

    public ExtendedActivityMonitor(Instrumentation instrumentation) {
        this(instrumentation, null);
    }

    public ExtendedActivityMonitor(Instrumentation instrumentation,
            IntentFilter filter) {
        // create our monitor
        activityInstanceMonitor = instrumentation.addMonitor(
                filter, null, false);

        this.activityMonitorThread = new Thread() {
            @Override
            public void run() {
                ThreadPoolExecutor executor =
                        new ThreadPoolExecutor(2, 5, 5, TimeUnit.SECONDS,
                                new ArrayBlockingQueue<Runnable>(5));

                while (true) {
                    /*
                     * ActivityMonitor's waiting is non-interruptable (who
                     * knows, why), so we check ourselves for interruption on a
                     * regular basis.
                     */
                    Activity activity = activityInstanceMonitor
                            .waitForActivityWithTimeout(CHECK_FOR_INTERRUPT_CYCLE_DURATION);
                    long startTime = System.currentTimeMillis();

                    if (activity != null) {
                        int activitiesCount = startedActivities.size();
                        if (activitiesCount > 0
                                && startedActivities.get(activitiesCount - 1).getActivity() == activity) {
                            continue;
                        }

                        // ok we got an activity, save the instance
                        synchronized (startedActivities) {
                            startedActivities.add(new StartedActivity(activity,
                                    startTime));
                        }
                        Log.i(getClass().getSimpleName(),
                                "Activity start: " + activity.getClass().getName());
                        // inform listeners within another thread
                        executor.submit(new ActivityStartListenerUpdater(
                                activity));
                    }
                    if (interrupted() || stopped) {
                        executor.shutdown();
                        // We were interrupted, stop waiting for new activites.
                        return;
                    }
                }
            }
        };
    }

    public void start() {
        this.activityMonitorThread.start();
        stopped = false;
    }

    /**
     * Returns the most recently started {@link Activity}. In most cases, this
     * will be the activity currently visible on screen.
     */
    public Activity getMostRecentlyStartedActivity() {
        List<StartedActivity> activities = getStartedActivities();

        if (activities.size() == 0) {
            return null;
        }

        return activities.get(activities.size() - 1).getActivity();
    }

    public List<StartedActivity> getStartedActivities() {
        List<StartedActivity> result = new ArrayList<StartedActivity>();

        synchronized (startedActivities) {
            Iterator<StartedActivity> iter = startedActivities.iterator();
            while (iter.hasNext()) {
                StartedActivity activity = iter.next();
                if (activity.getActivity().isFinishing()) {
                    iter.remove();
                }
                else {
                    result.add(activity);
                }
            }

            return new LinkedList<StartedActivity>(startedActivities);
        }
    }

    /**
     * Blocks until an {@link Activity} of the given type is started. The
     * instance of the started activity is then returned. If such an activity is
     * not started within the given amount of milliseconds, returns null.
     *
     * @param activityClass
     *            the type of activity to wait for
     * @param timeout
     *            amount to wait for activity start
     * @param timeUnit
     *            the unit of the timeout parameter
     * @return the activity waited for, or null if timeout was reached before
     *         any suitable activity was started
     */
    @SuppressWarnings("unchecked")
    public final <T extends Activity> T waitForActivity(
            Class<T> activityClass, long timeout, TimeUnit timeUnit) {
        long timeoutInMs = timeUnit.toMillis(timeout);

        Activity mostRecentlyStartedActivity = getMostRecentlyStartedActivity();
        if (mostRecentlyStartedActivity != null
                && mostRecentlyStartedActivity.getClass().equals(
                        activityClass)) {
            return (T) mostRecentlyStartedActivity;
        }

        int startedActivitiesCount = startedActivities.size();
        if (startedActivitiesCount > 0) {
            StartedActivity startedActivity = startedActivities.get(startedActivitiesCount - 1);
            if (startedActivity.getActivity().getClass().equals(activityClass)) {
                return (T) startedActivity.getActivity();
            }
        }

        // we need some kind of container to be shared between two threads
        final List<T> activityContainer = new LinkedList<T>();

        // register the listener, we are now informed when the activity starts
        registerActivityStartListener(activityClass,
                new ActivityStartListener() {
                    public void started(Activity activity) {
                        synchronized (activityContainer) {
                            // OK, the activity has been started. Put its
                            // instance in the container and notify.
                            activityContainer.add((T) activity);
                            activityContainer.notifyAll();
                        }
                    }
                });

        // Now, wait for the activity start by waiting on the container object.
        synchronized (activityContainer) {
            try {
                long time = System.currentTimeMillis();
                while (activityContainer.isEmpty()) {
                    activityContainer.wait(2000);
                    if (System.currentTimeMillis() - time > timeoutInMs) {
                        return null;
                    }
                }
            }
            catch (InterruptedException e) {
            }

            if (activityContainer.size() > 0) {
                return activityContainer.get(0);
            }
        }

        /*
         * Container was empty, we were either interrupted or more likely, the
         * timeout was reached. Return null.
         */
        return null;
    }

    public void stop() {
        stopped = true;
        activityMonitorThread.interrupt();
    }

    public void clear() {
        synchronized (startedActivities) {
            startedActivities.clear();
            activityStartListeners.clear();
        }
    }

    /*
     * Not synchronized, do that in the caller code.
     */
    private List<ActivityStartListener> getActivityStartListeners(
            Class<? extends Activity> activityClass) {
        List<ActivityStartListener> result =
                this.activityStartListeners.get(activityClass);
        if (result == null) {
            result = new ArrayList<ActivityStartListener>();
            this.activityStartListeners.put(activityClass, result);
        }
        return result;
    }

    private void registerActivityStartListener(
            Class<? extends Activity> activityClass,
            ActivityStartListener listener) {
        synchronized (this.activityStartListeners) {
            List<ActivityStartListener> listeners =
                    getActivityStartListeners(activityClass);
            listeners.add(listener);
        }
    }

    class ActivityStartListenerUpdater implements Callable<Void>
    {
        private final Activity activity;

        public ActivityStartListenerUpdater(Activity activity) {
            this.activity = activity;
        }

        public Void call() {
            synchronized (activityStartListeners) {
                List<ActivityStartListener> listeners =
                        getActivityStartListeners(
                        activity.getClass());
                for (ActivityStartListener listener : listeners) {
                    listener.started(activity);
                }
            }
            return null;
        }
    };
}


/*
 * Copyright 2010 akquinet
 * 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.akquinet.android.marvin;

import org.hamcrest.Matcher;

import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import de.akquinet.android.marvin.matchers.HasText;
import de.akquinet.android.marvin.matchers.IsEnabled;
import de.akquinet.android.marvin.matchers.IsOnScreen;
import de.akquinet.android.marvin.matchers.IsVisible;
import de.akquinet.android.marvin.matchers.ViewGroupComparison;

/**
 * A set of Hamcrest matchers for Android.
 *
 * @author Philipp Kumar
 */
public class AndroidMatchers
{
    /**
     * Evaluates to true if the value is a {@link TextView} with a text equal to
     * the parameter.
     */
    public static <T extends View> Matcher<T> hasText(String text) {
        return HasText.<T> hasText(text);
    }

    /**
     * Evaluates to true if the view is enabled.
     */
    public static <T extends View> Matcher<T> isEnabled() {
        return IsEnabled.<T> isEnabled();
    }

    /**
     * Evaluates to true if the view is not enabled.
     */
    public static <T extends View> Matcher<T> isNotEnabled() {
        return IsEnabled.<T> isNotEnabled();
    }

    /**
     * Evaluates to true if the view is visible on the current screen, using the
     * given rootView as reference.
     */
    public static <T extends View> Matcher<T> isOnScreen(T rootView) {
        return IsOnScreen.<T> isOnScreen(rootView);
    }

    /**
     * Evaluates to true if the view is visible.
     */
    public static <T extends View> Matcher<T> isVisible() {
        return IsVisible.<T> isVisible();
    }

    /**
     * Evaluates to true if the view is not visible.
     */
    public static <T extends View> Matcher<T> isNotVisible() {
        return IsVisible.<T> isNotVisible();
    }

    /**
     * Has the {@link ViewGroup} more children than value?
     */
    public static <T extends ViewGroup> Matcher<T> equalChildrenCountAs(final int value) {
        return ViewGroupComparison.<T> equalChildrenCountAs(value);
    }

    public static <T extends ViewGroup> Matcher<T> lessChildrenOrEqual(final int value) {
        return ViewGroupComparison.<T> lessChildrenOrEqual(value);
    }

    public static <T extends ViewGroup> Matcher<T> lessChildrenThan(final int value) {
        return ViewGroupComparison.<T> lessChildrenThan(value);
    }

    public static <T extends ViewGroup> Matcher<T> moreChildrenOrEqual(final int value) {
        return ViewGroupComparison.<T> moreChildrenOrEqual(value);
    }

    public static <T extends ViewGroup> Matcher<T> moreChildrenThan(final int value) {
        return ViewGroupComparison.<T> moreChildrenThan(value);
    }
}


package de.akquinet.android.marvin.matchers;

import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import android.view.ViewGroup;

public class ViewGroupComparison<T extends ViewGroup> extends TypeSafeMatcher<T>
{
    private static final int LESS_THAN = -1;
    private static final int GREATER_THAN = 1;
    private static final int EQUAL = 0;
    private final int childCount;
    private final int minCompare, maxCompare;

    private ViewGroupComparison(int childCount, int minCompare, int maxCompare) {
        this.childCount = childCount;
        this.minCompare = minCompare;
        this.maxCompare = maxCompare;
    }

    @Override
    public boolean matchesSafely(T viewGroup) {
        int compare = Integer.signum(viewGroup.getChildCount() - childCount);
        return minCompare <= compare && compare <= maxCompare;
    }

    @Override
    public void describeMismatchSafely(T viewGroup, Description mismatchDescription) {
        mismatchDescription.appendValue("child count of " + viewGroup).appendText(" was ")
                         .appendText(comparison(viewGroup.getChildCount() - childCount))
                         .appendText(" ").appendValue(childCount);
    };

    public void describeTo(Description description) {
        description.appendText("a child count ").appendText(comparison(minCompare));
        if (minCompare != maxCompare) {
            description.appendText(" or ").appendText(comparison(maxCompare));
        }
        description.appendText(" ").appendValue(childCount);
    }

    private String comparison(int compare) {
        if (compare == EQUAL) {
            return "equal to";
        }
        else if (compare > EQUAL) {
            return "greater than";
        }
        else {
            return "less than";
        }
    }

    /**
     * Is value = expected?
     */
    @Factory
    public static <T extends ViewGroup> Matcher<T> equalChildrenCountAs(int value) {
        return new ViewGroupComparison<T>(value, EQUAL, EQUAL);
    }

    /**
     * Is value > expected?
     */
    @Factory
    public static <T extends ViewGroup> Matcher<T> moreChildrenThan(int value) {
        return new ViewGroupComparison<T>(value, GREATER_THAN, GREATER_THAN);
    }

    /**
     * Is value >= expected?
     */
    @Factory
    public static <T extends ViewGroup> Matcher<T> moreChildrenOrEqual(int value) {
        return new ViewGroupComparison<T>(value, EQUAL, GREATER_THAN);
    }

    /**
     * Is value < expected?
     */
    @Factory
    public static <T extends ViewGroup> Matcher<T> lessChildrenThan(int value) {
        return new ViewGroupComparison<T>(value, LESS_THAN, LESS_THAN);
    }

    /**
     * Is value <= expected?
     */
    @Factory
    public static <T extends ViewGroup> Matcher<T> lessChildrenOrEqual(int value) {
        return new ViewGroupComparison<T>(value, LESS_THAN, EQUAL);
    }
}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.Measure;
import org.votesmart.data.Measures;

/**
 * <pre>
 * Ballot Measure Class
 * * - Required
 * * - Multiple rows
 *
 * Measure.getMeasuresByYearState
 * This method returns a list of state ballot measures in a given year.
 * Input: year*, stateId*
 * Output: {@link Measures}
 *
 * This method returns a single Ballot Measure detail.
 * Input: measureId*
 * Output: {@link Measure}
 *
 * =========== EXAMPLE USAGE =================
 *
 * // Ballot Measures
 * MeasureClass measureClass = new MeasureClass();
 *
 * // Get measures in 2012 state election
 * Measures measures = measureClass.getMeasuresByYearState("2012", state.stateId);
 *
 * Measure measure = measureClass.getMeasure(measures.measure.get(0).measureId);
 * </pre>
 *
 */
public class MeasureClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public MeasureClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public MeasureClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method returns a list of state ballot measures in a given year.
	 *
	 * @param year
	 * @param stateId
	 * @return {@link Measures}: List of minimal measure information.
	 */
	public Measures getMeasuresByYearState(String year, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Measure.getMeasuresByYearState", new ArgMap("year", year, "stateId", stateId), Measures.class );
	}

	/**
	 * This method returns a single Ballot Measure detail.
	 *
	 * @param measureId
	 * @return {@link Measure}: detail on single measure
	 */
	public Measure getMeasure(String measureId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Measure.getMeasure", new ArgMap("measureId", measureId), Measure.class );
	}

}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.Rating;
import org.votesmart.data.Sig;
import org.votesmart.data.Sigs;
import org.votesmart.data.SigRating;
import org.votesmart.data.Categories;
import org.votesmart.data.CandidateRating;

/**
 * <pre>
 * Rating Class
 *
 * * - Required
 * * - Multiple rows
 *
 * Rating.getCategories
 * This method dumps categories that contain released ratingss according to state.
 * Input: stateId (default: 'NA')
 * Output: {@link Categories}
 *
 * Rating.getSigList
 * This method dumps Special Interest Groups according to category and state.
 * Input: categoryId*, stateId (default: 'NA')
 * Output: {@link Sigs}
 *
 * Rating.getSig
 * This method dumps detailed information an a Special Interest Group.
 * Input: sigId*
 * Output: {@link Sig}
 *
 * Rating.getSigRatings
 * This method dumps all ratings(scorecards) by a Special Interest Group.
 * Input: sigId*
 * Output: {@link SigRating}
 *
 * Rating.getCandidateRating
 * This method dumps a candidate's rating by an SIG.
 * Input: candidateId*, sigId
 * Output: {@link CandidateRating}
 *
 * Rating.getRating
 * This method dumps all candidate ratings from a scorecard by an SIG.
 * Input: ratingId*
 * Output: {@link Rating}
 *
 * =========== EXAMPLE USAGE ==================
 *
 * RatingClass ratingClass = new RatingClass();
 *
 * // all categories
 * Categories categories = ratingClass.getCategories();
 *
 * // state categories
 * categories = ratingClass.getCategories(state.stateId);
 * CategoryMin category = categories.category.get(0)
 *
 * // state sigs (Special Interest Groups)
 * Sigs sigs = ratingClass.getSigList(category.categoryId, state.stateId);
 * Sigs.Sig sigsSig = sigs.sig.get(0);
 *
 * // Sig
 * Sig sig = ratingClass.getSig(sigs.sig.get(0).sigId);
 * </pre>
 *
 */
public class RatingClass extends ClassesBase {

	/**
	 * Constructor for testing purposes
	 *
	 * @param api
	 */
	public RatingClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public RatingClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method dumps categories that contain released ratings according to state.
	 * Input: stateId (default: 'NA')
	 *
	 * @return {@link Categories}
	 */
	public Categories getCategories() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getCategories", null, Categories.class );
	}

	/**
	 * This method dumps categories that contain released ratings according to state.
	 * Input: stateId (default: 'NA')
	 *
	 * @param stateId
	 * @return {@link Categories}
	 */
	public Categories getCategories(String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getCategories", new ArgMap("stateId", stateId), Categories.class );
	}

	/**
	 * This method dumps Special Interest Groups according to category and state.
	 * Input: categoryId*, stateId (default: 'NA')
	 *
	 * @param categoryId
	 * @return {@link Sigs}
	 */
	public Sigs getSigList(String categoryId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getSigList", new ArgMap("categoryId", categoryId), Sigs.class );
	}

	/**
	 * This method dumps Special Interest Groups according to category and state.
	 * Input: categoryId*, stateId (default: 'NA')
	 *
	 * @param categoryId
	 * @param stateId
	 * @return {@link Sigs}
	 */
	public Sigs getSigList(String categoryId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getSigList", new ArgMap("categoryId", categoryId, "stateId", stateId), Sigs.class );
	}

	/**
	 * This method dumps detailed information an a Special Interest Group.
	 * Input: sigId*
	 *
	 * @param sigId
	 * @return {@link Sig}
	 */
	public Sig getSig(String sigId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getSig", new ArgMap("sigId", sigId), Sig.class );
	}

	/**
	 * This method dumps all ratings(scorecards) by a Special Interest Group.
	 * Input: sigId*
	 *
	 * @param sigId
	 * @return {@link SigRating}
	 */
	public SigRating getSigRatings(String sigId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getSigRatings", new ArgMap("sigId", sigId), SigRating.class );
	}

	/**
	 * This method dumps a candidate's rating by an SIG.
	 *
	 * @param candidateId
	 * @return {@link CandidateRating}
	 */
	public CandidateRating getCandidateRating(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getCandidateRating", new ArgMap("candidateId", candidateId), CandidateRating.class );
	}

	/**
	 * This method dumps a candidate's rating by an SIG.
	 *
	 * @param candidateId
	 * @param sigId
	 * @return {@link CandidateRating}
	 */
	public CandidateRating getCandidateRating(String candidateId, String sigId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getCandidateRating", new ArgMap("candidateId", candidateId, "sigId", sigId), CandidateRating.class );
	}

	/**
	 * This method dumps all candidate ratings from a scorecard by an SIG.
	 *
	 * @param ratingId
	 * @return {@link Rating}
	 * @throws VoteSmartException, VoteSmartErrorException
	 */
	public Rating getRating(String ratingId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Rating.getRating", new ArgMap("ratingId", ratingId), Rating.class );
	}

}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.Elections;
import org.votesmart.data.ElectionByZip;
import org.votesmart.data.StageCandidates;

/**
 * <pre>
 * Election Class
 *
 * * - Required
 * * - Multiple rows
 *
 * Election.getElection
 * This method grabs district basic election data according to electionId
 * Input: electionId*
 * Output: {@link Elections}
 *
 * Election.getElectionByYearState
 * This method grabs district basic election data according to year and stateid.
 * Input: year*, stateId(default: 'NA')
 * Output: {@link Elections}
 *
 * Election.getElectionByZip
 * This method grabs district basic election data according to zip code.
 * Input: zip5*, zip4(default: NULL), year(default: &gr;=current year
 * Output: {@link ElectionByZip}
 *
 * Election.getStageCandidates
 * This method grabs district basic election data according to electionId and stageId. Per state lists of a Presidential election are available by specifying the stateId.
 * Input: electionId*, stageId*, party (Default: ALL(NULL)), districtId (Default: All(NULL)), stateId (Default: election.stateId)
 * Output: {@link StageCandidates}
 *
 * ============ EXAMPLE USAGE ==============
 *
 * ElectionClass electionClass = new ElectionClass();
 *
 * // look up 2012 elections
 * Elections elections = electionClass.getElectionByYearState("2012", state.stateId);
 * Elections.ElectionStage election = elections.election.get(0);
 * Elections.ElectionStage.Stage stage = elections.election.get(0).stage.get(0);
 *
 * // a specific election
 * elections = electionClass.getElection(election.electionId);
 * election = elections.election.get(0);
 * </pre>
 *
 */
public class ElectionClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public ElectionClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public ElectionClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method grabs district IDs according to the office and state.
	 *
	 * @param electionId
	 * @return {@link Elections}:
	 */
	public Elections getElection(String electionId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getElection", new ArgMap("electionId", electionId), Elections.class );
	}

	/**
	 * This method grabs district basic election data according to year and stateid.
	 *
	 * @param year
	 * @return {@link Elections}
	 */
	public Elections getElectionByYearState(String year) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getElectionByYearState", new ArgMap("year", year), Elections.class );
	}

	/**
	 * This method grabs district basic election data according to year and stateid.
	 *
	 * @param year
	 * @param stateId
	 * @return {@link Elections}:
	 */
	public Elections getElectionByYearState(String year, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getElectionByYearState", new ArgMap("year", year, "stateId", stateId), Elections.class );
	}

	/**
	 * This method grabs district basic election data according to zip code.
	 *
	 * @param zip5
	 * @return {@link ElectionByZip}:
	 */
	public ElectionByZip getElectionByZip(String zip5) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getElectionByZip", new ArgMap("zip5", zip5), ElectionByZip.class );
	}

	/**
	 * This method grabs district basic election data according to zip code.
	 *
	 * @param zip5
	 * @param zip4
	 * @return {@link ElectionByZip}:
	 */
	public ElectionByZip getElectionByZip(String zip5, String zip4) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getElectionByZip", new ArgMap("zip5", zip5, "zip4", zip4), ElectionByZip.class );
	}

	/**
	 * This method grabs district basic election data according to zip code.
	 *
	 * @param zip5
	 * @param zip4
	 * @param year
	 * @return {@link ElectionByZip}:
	 */
	public ElectionByZip getElectionByZip(String zip5, String zip4, String year) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getElectionByZip", new ArgMap("zip5", zip5, "zip4", zip4, "year", year), ElectionByZip.class );
	}

	/**
	 * This method grabs district basic election data according to electionId and stageId.
	 * Per state lists of a Presidential election are available by specifying the stateId.
	 *
	 * @param electionId
	 * @param stageId
	 * @return {@link StageCandidates}:
	 */
	public StageCandidates getStageCandidates(String electionId, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getStageCandidates", new ArgMap("electionId", electionId, "stageId", stageId), StageCandidates .class );
	}

	/**
	 * This method grabs district basic election data according to electionId and stageId.
	 * Per state lists of a Presidential election are available by specifying the stateId.
	 *
	 * @param electionId
	 * @param stageId
	 * @param party
	 * @return {@link StageCandidates}:
	 */
	public StageCandidates getStageCandidates(String electionId, String stageId, String party) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getStageCandidates", new ArgMap("electionId", electionId, "stageId", stageId, "party", party), StageCandidates .class );
	}

	/**
	 * This method grabs district basic election data according to electionId and stageId.
	 * Per state lists of a Presidential election are available by specifying the stateId.
	 *
	 * @param electionId
	 * @param stageId
	 * @param party
	 * @param districtId
	 * @return {@link StageCandidates}:
	 */
	public StageCandidates getStageCandidates(String electionId, String stageId, String party, String districtId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getStageCandidates", new ArgMap("electionId", electionId, "stageId", stageId, "party", party, "districtId", districtId), StageCandidates .class );
	}

	/**
	 * This method grabs district basic election data according to electionId and stageId.
	 * Per state lists of a Presidential election are available by specifying the stateId.
	 *
	 * @param electionId
	 * @param stageId
	 * @param party
	 * @param districtId
	 * @param stateId
	 * @return {@link StageCandidates}:
	 */
	public StageCandidates getStageCandidates(String electionId, String stageId, String party, String districtId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Election.getStageCandidates", new ArgMap("electionId", electionId, "stageId", stageId, "party", party, "districtId", districtId, "stateId", stateId), StageCandidates .class );
	}
}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.AddressAddress;
import org.votesmart.data.AddressOffice;
import org.votesmart.data.WebAddress;

/**
 *

 * Address Class
 * * - Required
 * * - Multiple rows
 *
 * Address.getCampaign
 * This method grabs campaign office(s) and basic candidate information for the specified candidate.
 * Input: candidateId*
 * Output: {@link AddressOffice}
 *
 * Address.getCampaignWebAddress
 * This method grabs the campaign office's Web address(es) and basic candidate information for the specified candidate.
 * Input: candidateId*
 * Output: {@link WebAddress}
 *
 * Address.getCampaignByElection
 * This method grabs campaign office(s) and basic candidate information for the specified election.
 * Input: electionId*
 * Output: {@link AddressOffice}
 *
 * Address.getOffice
 * This method grabs office(s) and basic candidate information for the specified candidate.
 * Input: candidateId*
 * Output: {@link AddressOffice}
 *
 * Address.getOfficeWebAddress
 * This method grabs office's Web address(es) and basic candidate information for the specified candidate.
 * Input: candidateId*
 * Output: {@link WebAddress}
 *
 * Address.getOfficeByOfficeState
 * This method grabs office address and basic candidate information according to the officeId and state.
 * Input: officeId*, stateId (Default: 'NA')
 * Output: {@link AddressAddress}
 *
 * ==== EXAMPLE USAGE =====
 *
 * AddressClass addressClass = new AddressClass();
 *
 * // address of Office (State Assembly)
 * AddressAddress addressOffice = addressClass.getOfficeByOfficeState(office.officeId, state.stateId);
 *
 * // address of Official
 * AddressOffice addressOffical = addressClass.getOffice(candidate.candidateId)
 *
 * // WebAddress of Official
 * WebAddress webAddressOffical = addressClass.getOfficeWebAddress(candidate.candidateId);
 *

 */
public class AddressClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public AddressClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default constructor
	 */
	public AddressClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method grabs campaign office(s) and basic candidate information for the specified candidate.
	 *
	 * @param candidateId
	 * @return {@link AddressOffice}: address and list of office addresses.
	 */
	public AddressOffice getCampaign(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Address.getCampaign", new ArgMap("candidateId", candidateId), AddressOffice.class );
	}

	/**
	 * This method grabs the campaign office's Web address(es) and basic candidate information for the specified candidate.
	 *
	 * @param candidateId
	 * @return {@link WebAddress}: Candidate name and URL's
	 */
	public WebAddress getCampaignWebAddress(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Address.getCampaignWebAddress", new ArgMap("candidateId", candidateId), WebAddress.class );
	}

	/**
	 * This method grabs campaign office(s) and basic candidate information for the specified election.
	 *
	 * @param electionId
	 * @return {@link AddressOffice}: Candidate name and list of office addresses
	 */
	public AddressOffice getCampaignByElection(String electionId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Address.getCampaignByElection", new ArgMap("electionId", electionId), AddressOffice.class );
	}

	/**
	 * This method grabs office(s) and basic candidate information for the specified candidate.
	 *
	 * @param candidateId
	 * @return {@link AddressOffice}: Candidate name and list of office addresses
	 */
	public AddressOffice getOffice(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Address.getOffice", new ArgMap("candidateId", candidateId), AddressOffice.class );
	}

	/**
	 * This method grabs office's Web address(es) and basic candidate information for the specified candidate.
	 *
	 * @param candidateId
	 * @return {@link WebAddress}: Candidate name and list of URL's
	 */
	public WebAddress getOfficeWebAddress(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Address.getOfficeWebAddress", new ArgMap("candidateId", candidateId), WebAddress.class );
	}

	/**
	 * This method grabs office address and basic candidate information according to the officeId and state.
	 *
	 * @param officeId
	 * @return {@link AddressAddress}: Candidate name and list of offices
	 */
	public AddressAddress getOfficeByOfficeState(String officeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Address.getOfficeByOfficeState", new ArgMap("officeId", officeId), AddressAddress.class );
	}

	/**
	 * This method grabs office address and basic candidate information according to the officeId and state.
	 *
	 * @param officeId
	 * @param stateId
	 * @return {@link AddressAddress}: Candidate name and list of offices
	 */
	public AddressAddress getOfficeByOfficeState(String officeId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Address.getOfficeByOfficeState", new ArgMap("officeId", officeId, "stateId", stateId), AddressAddress.class );
	}

}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.DistrictList;

/**
 * <pre>
 * District Class
 *
 * District.getByOfficeState()
 * This method grabs district IDs according to the office and state.
 * Input: officeId*, stateId*, districtName(Default: Null)
 * Output: {@link DistrictList}
 *
 * District.getByZip()
 * This method grabs district IDs according to the zip code.
 * Input: zip5*, zip4 (Default: Null)
 * Output: {@link DistrictList}
 *
 * ============= EXAMPLE USAGE ===================
 *
 * DistrictClass districtClass = new DistrictClass();
 *
 * DistrictList districtList = districtClass.getByOfficeState(office.officeId, state.stateId);
 * DistrictList.District district = districtList.district.get(0);
 *
 * </pre>
 *
 */
public class DistrictClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public DistrictClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public DistrictClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method grabs district IDs according to the office and state.
	 *
	 * @param officeId
	 * @param stateId
	 * @return {@link DistrictList}:
	 */
	public DistrictList getByOfficeState( String officeId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("District.getByOfficeState", new ArgMap("officeId", officeId, "stateId", stateId), DistrictList.class );
	}

	/**
	 * This method grabs district IDs according to the office and state.
	 *
	 * @param officeId
	 * @param stateId
	 * @param districtName
	 * @return {@link DistrictList}:
	 */
	public DistrictList getByOfficeState( String officeId, String stateId, String districtName) throws VoteSmartException, VoteSmartErrorException {
		return api.query("District.getByOfficeState", new ArgMap("officeId", officeId, "stateId", stateId, "districtName", districtName), DistrictList.class );
	}

	/**
	 * This method grabs district IDs according to the zip code.
	 *
	 * @param zip5
	 * @return {@link DistrictList}:
	 */
	public DistrictList getByZip( String zip5) throws VoteSmartException, VoteSmartErrorException {
		return api.query("District.getByZip", new ArgMap("zip5", zip5), DistrictList.class );
	}

	/**
	 * This method grabs district IDs according to the zip code.
	 *
	 * @param zip5
	 * @param zip4
	 * @return {@link DistrictList}:
	 */
	public DistrictList getByZip( String zip5, String zip4) throws VoteSmartException, VoteSmartErrorException {
		return api.query("District.getByZip", new ArgMap("zip5", zip5, "zip4", zip4), DistrictList.class );
	}

}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.Branches;
import org.votesmart.data.Levels;
import org.votesmart.data.OfficeTypes;
import org.votesmart.data.Offices;

/**
 * <pre>
 * Office Class
 *
 * Office.getTypes
 * This method dumps all office types we keep track of
 * Input: none
 * Output: {@link OfficeTypes}
 *
 * Office.getBranches
 * This method dumps the branches of government and their IDs
 * Input: none
 * Output: {@link Branches}
 *
 * Office.getLevels
 * This method dumps the levels of government and their IDs
 * Input: none
 * Output: {@link Levels}
 *
 * Office.getOfficesByType
 * This method dumps offices we keep track of according to type.
 * Input: officeTypeId*
 * Output: {@link Offices}
 *
 * Office.getOfficesByLevel
 * This method dumps offices we keep track of according to level.
 * Input: levelId*
 * Output: {@link Offices}
 *
 * Office.getOfficesByTypeLevel
 * This method dumps offices we keep track of according to type and level.
 * Input: officeTypeId*, levelId*
 * Output: {@link Offices}
 *
 * Office.getOfficesByBranchLevel
 * This method dumps offices we keep track of according to branch and level.
 * Input: branchId*, levelId*
 * Output: {@link Offices}
 *
 * ============== EXAMPLE USAGE ============
 *
 * // Get general Information about offices
 * OfficeClass officeClass = new OfficeClass();
 *
 * // get Office.getBranches
 * Branches branches = officeClass.getBranches();
 * Branches.Branch officeBranch = branches.branch.get(1);
 *
 * // Office.getTypes
 * OfficeTypes officeTypes = officeClass.getTypes();
 * OfficeTypes.Type officeType  = officeTypes.type.get(5);
 *
 * // Office.getLevels
 * Levels levels = officeClass.getLevels();
 * Levels.Level officeLevel = levels.level.get(1);
 * </pre>
 *
 */
public class OfficeClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public OfficeClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public OfficeClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method dumps all office types we keep track of.
	 *
	 * @return {@link OfficeTypes}:
	 */
	public OfficeTypes getTypes() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Office.getTypes", null, OfficeTypes.class );
	}

	/**
	 * This method dumps the branches of government and their IDs.
	 *
	 * @return {@link Branches}:
	 */
	public Branches getBranches() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Office.getBranches", null, Branches.class );
	}

	/**
	 * This method dumps the levels of government and their IDs.
	 *
	 * @return {@link Levels}:
	 */
	public Levels getLevels() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Office.getLevels", null, Levels.class );
	}

	/**
	 * This method dumps offices we keep track of according to type.
	 *
	 * @param officeTypeId
	 * @return {@link Offices}:
	 */
	public Offices getOfficesByType(String officeTypeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Office.getOfficesByType", new ArgMap("officeTypeId", officeTypeId), Offices.class );
	}

	/**
	 * This method dumps offices we keep track of according to level.
	 *
	 * @param levelId
	 * @return {@link Offices}:
	 */
	public Offices getOfficesByLevel(String levelId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Office.getOfficesByLevel", new ArgMap("levelId", levelId), Offices.class );
	}

	/**
	 * This method dumps offices we keep track of according to type and level.
	 *
	 * @param officeTypeId
	 * @param officeLevelId
	 * @return {@link Offices}:
	 */
	public Offices getOfficesByTypeLevel(String officeTypeId, String officeLevelId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Office.getOfficesByTypeLevel", new ArgMap("officeTypeId", officeTypeId, "officeLevelId", officeLevelId), Offices.class );
	}

	/**
	 * This method dumps offices we keep track of according to branch and level.
	 *
	 * @param branchId
	 * @param levelId
	 * @return {@link Offices}:
	 */
	public Offices getOfficesByBranchLevel(String branchId, String levelId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Office.getOfficesByBranchLevel", new ArgMap("branchId", branchId, "levelId", levelId), Offices.class );
	}

}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.Cities;
import org.votesmart.data.Counties;
import org.votesmart.data.LocalCandidateList;

/**
 * <pre>
 *  Local Class
 *
 *  Local.getCounties()
 *  Fetches counties in a state
 *  Input: stateId*
 *  Output: {@link Counties}
 *
 *  Local.getCities()
 *  Fetches cities in a state
 *  Input: stateId*
 *  Output: {@link Cities}
 *
 *  Local.getOfficials()
 *  Fetches officials for a locality
 *  Input: localId*
 *  Output: {@link LocalCandidateList}
 *
 *  ============= EXAMPLE USAGE =============
 *
 *  LocalClass localClass = new LocalClass();
 *
 *  // get counties
 *  Counties counties = localClass.getCounties(state.stateId);
 *  Counties.County county = counties.county.get(0);
 *
 *  // get cities
 *  Cities cities = localClass.getCities(state.stateId);
 *  Cities.City city = cities.city.get(0);
 *
 *  // county official
 *  LocalCandidateList localCandidates = localClass.getOfficials(county.localId);
 *  LocalCandidateList.Candidate localCandidate = localCandidates.candidate.get(0);
 *  </pre>
 */
public class LocalClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public LocalClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public LocalClass() throws VoteSmartException {
		super();
	}

	/**
	 * Fetches counties in a state.
	 *
	 * @param stateId
	 * @return {@link Counties}:
	 */
	public Counties getCounties(String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Local.getCounties", new ArgMap("stateId", stateId), Counties.class );
	}

	/**
	 * Fetches cities in a state.
	 *
	 * @param stateId
	 * @return {@link Cities}:
	 */
	public Cities getCities(String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Local.getCities", new ArgMap("stateId", stateId), Cities.class );
	}

	/**
	 * Fetches officials for a locality.
	 *
	 * @param localId
	 * @return {@link LocalCandidateList}:
	 */
	public LocalCandidateList getOfficials(String localId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Local.getOfficials", new ArgMap("localId", localId), LocalCandidateList.class );
	}
}


package org.votesmart.api;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.votesmart.data.ErrorBase;

/**
 * VoteSmart API. This is a fully static class so that
 * it gets initialized once and then any API class
 * will not have to initialize it again.
 *
 *
 *
 */
public class VoteSmart implements VoteSmartAPI {
	private static final Logger logger = Logger.getLogger(VoteSmart.class.getName());
	public static final String apikeyKey = "apikey";
	public static final String cacheKey = "cache";
	private static String apiKey = null;
	private static String apiServer = "api.votesmart.org";
	private static String cache;
    private static Unmarshaller unmarshaller;
    private static boolean checkCache;
    private static boolean suspendCache;

    /**
     * Initialize the API. Called instead of a constructor.
     *
     * @param bundle
     */
	public VoteSmart(ResourceBundle bundle) throws VoteSmartException {
		// API not needed for testing
		if ( !bundle.containsKey(apikeyKey)) throw new VoteSmartException("No apikey found in openstates.properties");
		apiKey = bundle.getString(apikeyKey);
		if ( apiKey == null ) throw new VoteSmartException("apikey not set in openstates.properties");
		if ( bundle.containsKey(cacheKey)) {
			cache = bundle.getString(cacheKey);
			if ( cache.lastIndexOf('/') != (cache.length()-1)) cache = cache+"/";
			File cacheFile = new File(cache);
			logger.config("cache directory:" + cacheFile.toString());
			if ( !cacheFile.exists() ) {
				logger.config("Creating directories for cache:" + cacheFile.toString());
				cacheFile.mkdirs();
			}
		}
		checkCache = true;
		suspendCache = false;
		try {
			unmarshaller = JAXBContext.newInstance( "org.votesmart.data" ).createUnmarshaller();
		} catch (JAXBException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Modify whether or not the cache is first checked for files.
	 * Note that any JSON read will always be written to the
	 * cache.
	 *
	 * @param checkCache the check cache
	 */
	public static void setCache(boolean checkCache) {
		if ( VoteSmart.checkCache != checkCache ) logger.fine("Setting checkCache to " + checkCache );
		VoteSmart.checkCache = checkCache;
	}

	/**
	 * Get the current state of the caching flag
	 *
	 * @return the current state of the caching flag
	 */
	public static boolean getCache() {
		return VoteSmart.checkCache;
	}

	/**
	 * Disable caching for one call, and one call only.
	 *
	 * This call disables caching for the next call
	 * regardless of the current state of caching. It
	 * does not disable the current state of caching.
	 *
	 */
	public static void suspendCache() {
		VoteSmart.suspendCache = true;
	}

	/**
	 * Queries the API server for the information requested
	 *
	 * @param method
	 * @param argMap
	 * @param responseType
	 * @throws VoteSmartErrorException
	 *
	 */
	public <T> T query(String method, ArgMap argMap, Class<T> responseType) throws VoteSmartException, VoteSmartErrorException {
		BufferedReader reader = null;
		HttpURLConnection conn = null;
		String charSet = "utf-8";
		try {
			if ( isCaching(method, argMap) ) {
				File file = getCacheFile(method, argMap);

				long fileLength = file.length();
				logger.fine("Length of File in cache:" + fileLength + ": " + file.getName());
				if ( fileLength == 0L ) {
					VoteSmart.cacheFileFromAPI(method, argMap, file);
				}
				reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), charSet));
			} else {
				conn = VoteSmart.getConnectionFromAPI(method, argMap);
				charSet = getCharset(conn);
				reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), charSet));
			}

	        JAXBElement<T> e = unmarshaller.unmarshal( new StreamSource( reader ), responseType );
	        if ( e.getName().getLocalPart().equals("error") ) {
//		        ErrorBase error = unmarshaller.unmarshal( new StreamSource( reader = new StringReader(XMLStr) ), ErrorBase.class ).getValue();
	        	throw new VoteSmartErrorException( ((ErrorBase)e.getValue()), method, argMap );
	        } else {
	        	return e.getValue();
	        }
/*
 	        Object o = unmarshaller.unmarshal( new StreamSource( reader ) );
	        if ( o instanceof ErrorBase ) {
	        	throw new VoteSmartErrorException((ErrorBase) o, method, argMap);
	        } else {
		        @SuppressWarnings("unchecked")
				T e = (T) o;
		        return e;
	        }
*/
		} catch ( JAXBException e ) {
			throw new VoteSmartException(e);
		} catch (URISyntaxException e) {
			throw new VoteSmartException(e);
		} catch (IOException e) {
			throw new VoteSmartException(e);
		} finally {
			suspendCache = false;
			if ( conn != null ) conn.disconnect();
			if ( reader != null ) {
				try {
					reader.close();
				} catch (IOException e) {
					throw new VoteSmartException(e);
				}
			}
		}
	}

	private boolean isCaching(String method, ArgMap argMap) {
		if ( VoteSmart.cache == null ) return false;
		if ( VoteSmart.suspendCache == true ) return false;
		if ( VoteSmart.checkCache == false ) return false;
		return true;
	}

	private static File getCacheFile(String method, ArgMap argMap) {
		StringBuilder filename = new StringBuilder( VoteSmart.cache + method);
		// do args if any
		if ( argMap!= null ) {
			for (String key: argMap.keySet() )
			{
				String value = argMap.get(key);
				if ( value == null ) continue;
				filename.append('.');
				filename.append( key );
				filename.append('.');
				filename.append( value );
			}
		}
		filename.append(".xml" );

		// return a file object
		return new File(filename.toString());
	}

	private static void cacheFileFromAPI(String method, ArgMap argMap, File file) throws URISyntaxException, IOException, VoteSmartException {
		BufferedReader breader = null;
		BufferedWriter bwriter = null;
		HttpURLConnection conn = null;
		try {
		    char[] buffer = new char[2^13];
			conn = getConnectionFromAPI(method, argMap);
			String charSet = getCharset(conn);
			breader = new BufferedReader(new InputStreamReader( conn.getInputStream(), charSet ) );
			bwriter = new BufferedWriter( new OutputStreamWriter( new FileOutputStream(file), Charset.forName("utf-8")) );
			int read;
			while ( (read = breader.read(buffer)) != -1 ) {
				bwriter.write(buffer, 0, read);
			}
		} finally {
			if ( conn != null ) conn.disconnect();
			if ( bwriter != null ) bwriter.close();
			if ( breader != null ) breader.close();
		}
	}

	private static HttpURLConnection getConnectionFromAPI(String method, ArgMap argMap) throws URISyntaxException, IOException, VoteSmartException {
	    HttpURLConnection con = null;
			StringBuilder terms = new StringBuilder();
		// Iterate through the keys and their values, both are important
		if ( argMap != null ) {
			for (String key: argMap.keySet() )
			{
				String value = argMap.get(key);
				if ( value == null ) continue;
				terms.append( '&' )
				.append( key )
				.append('=' )
				.append( value );		// URL encoding is done by the URI constructor
			}
		}

		// construct the URI ..
		URI uri = new URI(
			"http",
			null,
			apiServer,
			-1,
			"/" + method,
			"key=" + apiKey + "&output=XML" + terms.toString(),
			null
		);
		logger.fine(uri.toString());

		con = (HttpURLConnection) uri.toURL().openConnection();
	    con.setRequestMethod("GET");
	    con.setRequestProperty("Accept", "text/xml, application/xml");
	    con.connect();
	    return con;
	}

	private static String getCharset(HttpURLConnection con) throws VoteSmartException, IOException {
	    // better check it first
	    if (con.getResponseCode() / 100 != 2) {
	    	String msg = con.getResponseMessage();
	    	con.disconnect();
	    	throw new VoteSmartException(msg);
	    }
	    String contentType = con.getHeaderField("Content-Type");
	    String charset = null;
	    for (String param : contentType.replace(" ", "").split(";")) {
	        if (param.startsWith("charset=")) {
	            charset = param.split("=", 2)[1];
	            break;
	        }
	    }
	    if ( charset == null ) {
	    	logger.fine("Defaulting to utf-8 charset");
	    	charset = "utf-8";
	    }
	    return charset;
	}
}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.CandidateList;

/**
 * <pre>
 * Officials Class
 *
 * * - Required
 * * - Multiple rows
 *
 * Officials.getStatewide()
 * This method grabs a list of officials according to state representation
 * Input: stateId(default: 'NA')
 * Output: {@link CandidateList}
 *
 * Officials.getByOfficeState()
 * This method grabs a list of officials according to office and state representation.
 * Input: officeId*, stateId(default: 'NA')
 * Output: {@link CandidateList}
 *
 * Officials.getByOfficeTypeState()
 * This method grabs a list of officials according to office type and state representation.
 * Input: officeTypeId*, stateId(default: 'NA')
 * Output: {@link CandidateList}
 *
 * Officials.getByLastname()
 * This method grabs a list of officials according to a lastName match.
 * Input: lastName*
 * Output: {@link CandidateList}
 *
 * Officials.getByLevenshtein()
 * This method grabs a list of officials according to a fuzzy lastName match.
 * Input: lastName*
 * Output: {@link CandidateList}
 *
 * Officials.getByDistrict()
 * This method grabs a list of officials according to the district they are running for.
 * Input: districtId*
 * Output: {@link CandidateList}
 *
 * Officials.getByZip()
 * This method grabs a list of officials according to the zip code they represent.
 * Input: zip5*, zip4(default: NULL)
 * Output: {@link CandidateList}
 *
 * =============== EXAMPLE USAGE ====================
 *
 * // Officials
 * OfficialsClass officialsClass = new OfficialsClass();
 *
 * // Officials
 * CandidateList candidates = officialsClass.getStatewide();
 *
 * // Officials for State
 * candidates = officialsClass.getStatewide(state.stateId);
 * CandidateList.Candidate candidate = candidates.candidate.get(0);
 *
 * // Officials for last officeType (Legislature), for state
 * candidates = officialsClass.getByOfficeTypeState(officeType.officeTypeId, state.stateId);
 * candidate = candidates.candidate.get(0);
 * </pre>
 *
 */
public class OfficialsClass extends ClassesBase {

	/**
	 * Constructor for testing purposes
	 *
	 * @param api
	 */
	public OfficialsClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default constructor
	 */
	public OfficialsClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method grabs a list of officials according to state representation.
	 *
	 * @return {@link CandidateList}
	 */
	public CandidateList getStatewide() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getStatewide", null, CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to state representation.
	 *
	 * @param stateId
	 * @return {@link CandidateList}
	 */
	public CandidateList getStatewide(String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getStatewide", new ArgMap("stateId", stateId), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to office and state representation.
	 *
	 * @param officeId
	 * @return {@link CandidateList}
	 */
	public CandidateList getByOfficeState(String officeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByOfficeState", new ArgMap("officeId", officeId), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to office and state representation.
	 *
	 * @param officeId
	 * @param stateId
	 * @return {@link CandidateList}
	 */
	public CandidateList getByOfficeState(String officeId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByOfficeState", new ArgMap("officeId", officeId, "stateId", stateId), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to office type and state representation.
	 *
	 * @param officeTypeId
	 * @return {@link CandidateList}
	 */
	public CandidateList getByOfficeTypeState(String officeTypeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByOfficeTypeState", new ArgMap("officeTypeId", officeTypeId), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to office type and state representation.
	 *
	 * @param officeTypeId
	 * @param stateId
	 * @return {@link CandidateList}
	 */
	public CandidateList getByOfficeTypeState(String officeTypeId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByOfficeTypeState", new ArgMap("officeTypeId", officeTypeId, "stateId", stateId), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to a lastName match.
	 *
	 * @param lastName
	 * @return {@link CandidateList}
	 */
	public CandidateList getByLastname(String lastName) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByLastname", new ArgMap("lastName", lastName), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to a fuzzy lastName match.
	 *
	 * @param lastName
	 * @return {@link CandidateList}
	 */
	public CandidateList getByLevenshtein(String lastName) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByLevenshtein", new ArgMap("lastName", lastName), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to the district they are running for.
	 *
	 * @param districtId
	 * @return {@link CandidateList}
	 */
	public CandidateList getByDistrict(String districtId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByDistrict", new ArgMap("districtId", districtId), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to the zip code they represent.
	 *
	 * @param zip5
	 * @return {@link CandidateList}
	 */
	public CandidateList getByZip(String zip5) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByZip", new ArgMap("zip5", zip5), CandidateList.class );
	}

	/**
	 * This method grabs a list of officials according to the zip code they represent.
	 *
	 * @param zip5
	 * @param zip4
	 * @return {@link CandidateList}
	 */
	public CandidateList getByZip(String zip5, String zip4) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Officials.getByZip", new ArgMap("zip5", zip5, "zip4", zip4), CandidateList.class );
	}

}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.AddlBio;
import org.votesmart.data.BioOld;
import org.votesmart.data.Bio;

/**
 * <pre>
 * CandidateBio Class
 *
 * *- Required
 * *- Multiple rows
 *
 * CandidateBio.getBio()
 * This method grabs the main bio for each candidate.
 * Input: candidateId*
 * Output: {@link BioOld}: Candidate biographical information
 *
 * CandidateBio.getAddlBio()
 * This method grabs the extended bio for each candidate that has one.
 * Input: candidateId*
 * Output: {@link AddlBio}: Additional items in a list.
 *
 * ====== EXAMPLE USAGE ========
 *
 * CandidateBioClass candidateBioClass = new CandidateBioClass();
 *
 * // Bio of Official
 * Bio bio = candidateBioClass.getBio(candidate.candidateId);
 * </pre>
 *
 */
public class CandidateBioClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public CandidateBioClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public CandidateBioClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method grabs the main bio for each candidate.
	 *
	 * @param candidateId
	 * @return {@link BioOld}: Candidate biographical information
	 */
/*
	public BioOld getBio(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("CandidateBio.getBio", new ArgMap("candidateId", candidateId), BioOld.class );
	}
*/
	/**
	 * This method grabs the extended bio for each candidate that has one.
	 *
	 * @param candidateId
	 * @return {@link AddlBio}: Additional items in a list.
	 */
	public AddlBio getAddlBio(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("CandidateBio.getAddlBio", new ArgMap("candidateId", candidateId), AddlBio.class );
	}

	/**
	 * This method grabs the extended bio for each candidate that has one.
	 * It uses the updated version 'getDetailedBio' of the call.
	 *
	 * @param candidateId
	 * @return {@link AddlBio}: Additional items in a list.
	 */
	public Bio getBio(String candidateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("CandidateBio.getDetailedBio", new ArgMap("candidateId", candidateId), Bio.class );
	}
}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.CandidateList;

/**
 *

 * Candidates Class
 *
 * * - Required
 * * - Multiple rows
 *
 * Candidates.getByOfficeState()
 * This method grabs a list of candidates according to office and state representation.
 * Input: officeId*, stateId(default: 'NA'), electionYear(default: >= current year), stageId
 * Output: {@link CandidateList}
 *
 * Candidates.getByOfficeTypeState()
 * This method grabs a list of candidates according to office type and state representation.
 * Input: officeTypeId*, stateId(default: 'NA'), electionYear(default: >= current year), stageId
 * Output: {@link CandidateList}
 *
 * Candidates.getByLastname()
 * This method grabs a list of candidates according to a lastname match.
 * Input: lastName*, electionYear(default: >= current year), stageId
 * Output: {@link CandidateList}
 *
 * Candidates.getByLevenshtein()
 * This method grabs a list of candidates according to a fuzzy lastname match.
 * Input: lastName*, electionYear(default: >= current year), stageId
 * Output: {@link CandidateList}
 *
 * Candidates.getByElection()
 * This method grabs a list of candidates according to the election they are running in.
 * Input: electionId*, stageId
 * Output: {@link CandidateList}
 *
 * Candidates.getByDistrict()
 * This method grabs a list of candidates according to the district they represent.
 * Input: districtId*, electionYear(default: >= current year), stageId
 * Output: {@link CandidateList}
 *
 * Candidates.getByZip()
 * This method grabs a list of candidates according to the zip code they represent.
 * Input: zip5*, electionYear(default: >= current year), zip4(default: NULL), stageId
 * Output: {@link CandidateList}
 *
 * ========= EXAMPLE USAGE =============
 *
 * CandidatesClass candidatesClass = new CandidatesClass();
 *
 * // Candidates for last office, for state
 * CandidateList candidates = candidatesClass.getByOfficeState(office.officeId, state.stateId);
 *
 * // Candidates for last office, for state
 * candidates = candidatesClass.getByOfficeTypeState(officeType.officeTypeId, state.stateId);
 *

 */
public class CandidatesClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public CandidatesClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public CandidatesClass() throws VoteSmartException {
		super();
	}

	/**
	 * This method grabs a list of candidates according to office and state representation.
	 *
	 * @param officeId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeState(String officeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeState", new ArgMap("officeId", officeId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to office and state representation.
	 *
	 * @param officeId
	 * @param stateId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeState(String officeId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeState", new ArgMap("officeId", officeId, "stateId", stateId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to office and state representation.
	 *
	 * @param officeId
	 * @param stateId
	 * @param electionYear
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeState(String officeId, String stateId, String electionYear) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeState", new ArgMap("officeId", officeId, "stateId", stateId, "electionYear", electionYear), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to office and state representation.
	 *
	 * @param officeId
	 * @param stateId
	 * @param electionYear
	 * @param stageId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeState(String officeId, String stateId, String electionYear, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeState", new ArgMap("officeId", officeId, "stateId", stateId, "electionYear", electionYear, "stageId", stageId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to office type and state representation.
	 *
	 * @param officeTypeId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeTypeState(String officeTypeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeTypeState", new ArgMap("officeTypeId", officeTypeId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to office type and state representation.
	 *
	 * @param officeTypeId
	 * @param stateId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeTypeState(String officeTypeId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeTypeState", new ArgMap("officeTypeId", officeTypeId, "stateId", stateId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to office type and state representation.
	 *
	 * @param officeTypeId
	 * @param stateId
	 * @param electionYear
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeTypeState(String officeTypeId, String stateId, String electionYear) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeTypeState", new ArgMap("officeTypeId", officeTypeId, "stateId", stateId, "electionYear", electionYear), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to office type and state representation.
	 *
	 * @param officeTypeId
	 * @param stateId
	 * @param electionYear
	 * @param stageId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByOfficeTypeState(String officeTypeId, String stateId, String electionYear, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByOfficeTypeState", new ArgMap("officeTypeId", officeTypeId, "stateId", stateId, "electionYear", electionYear, "stageId", stageId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a lastname match.
	 *
	 * @param lastName
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByLastname(String lastName) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByLastname", new ArgMap("lastName", lastName), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a lastname match.
	 *
	 * @param lastName
	 * @param electionYear
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByLastname(String lastName, String electionYear) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByLastname", new ArgMap("lastName", lastName, "electionYear", electionYear), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a lastname match.
	 *
	 * @param lastName
	 * @param electionYear
	 * @param stageId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByLastname(String lastName, String electionYear, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByLastname", new ArgMap("lastName", lastName, "electionYear", electionYear, "stageId", stageId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a fuzzy lastname match.
	 *
	 * @param lastName
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByLevenshtein(String lastName) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByLevenshtein", new ArgMap("lastName", lastName), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a fuzzy lastname match.
	 *
	 * @param lastName
	 * @param electionYear
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByLevenshtein(String lastName, String electionYear) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByLevenshtein", new ArgMap("lastName", lastName, "electionYear", electionYear), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a fuzzy lastname match.
	 *
	 * @param lastName
	 * @param electionYear
	 * @param stageId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByLevenshtein(String lastName, String electionYear, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByLevenshtein", new ArgMap("lastName", lastName, "electionYear", electionYear, "stageId", stageId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a fuzzy lastname match.
	 *
	 * @param electionId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByElection(String electionId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByElection", new ArgMap("electionId", electionId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to a fuzzy lastname match.
	 *
	 * @param electionId
	 * @param stageId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByElection(String electionId, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByElection", new ArgMap("electionId", electionId, "stageId", stageId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to the district they represent.
	 *
	 * @param districtId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByDistrict(String districtId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByDistrict", new ArgMap("districtId", districtId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to the district they represent.
	 *
	 * @param districtId
	 * @param electionYear
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByDistrict(String districtId, String electionYear) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByDistrict", new ArgMap("districtId", districtId, "electionYear", electionYear), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to the district they represent.
	 *
	 * @param districtId
	 * @param electionYear
	 * @param stageId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByDistrict(String districtId, String electionYear, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByDistrict", new ArgMap("districtId", districtId, "electionYear", electionYear, "stageId", stageId), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to the district they represent.
	 *
	 * @param zip5
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByZip(String zip5) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByZip", new ArgMap("zip5", zip5), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to the district they represent.
	 *
	 * @param zip5
	 * @param electionYear
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByZip(String zip5, String electionYear) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByZip", new ArgMap("zip5", zip5, "electionYear", electionYear), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to the district they represent.
	 *
	 * @param zip5
	 * @param electionYear
	 * @param zip4
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByZip(String zip5, String electionYear, String zip4) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByZip", new ArgMap("zip5", zip5, "electionYear", electionYear, "zip4", zip4), CandidateList.class );
	}

	/**
	 * This method grabs a list of candidates according to the district they represent.
	 *
	 * @param zip5
	 * @param electionYear
	 * @param zip4
	 * @param stageId
	 * @return {@link CandidateList}: list of detailed candidate information.
	 */
	public CandidateList getByZip(String zip5, String electionYear, String zip4, String stageId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Candidates.getByZip", new ArgMap("zip5", zip5, "electionYear", electionYear, "zip4", zip4, "stageId", stageId), CandidateList.class );
	}

}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.Committee;
import org.votesmart.data.CommitteeMembers;
import org.votesmart.data.CommitteeTypes;
import org.votesmart.data.Committees;

/**
 * <pre>
 * Committee Class
 *
 * * - Required
 * * - Multiple rows
 *
 * Committee.getTypes()
 * Returns the committee types(house, senate, joint, etc)
 * Input: none
 * Output: {@link CommitteeTypes}
 *
 * Committee.getCommitteesByTypeState()
 * Returns the list of committees that fit the criteria
 * Input: typeId(Default: All), stateId (Default: NA(fed))
 * Output: {@link Committees}
 *
 * Committee.getCommittee()
 * Returns detailed committee data.
 * Input: committeeId*
 * Output: {@link Committee}
 *
 * Committee.getCommitteeMembers()
 * Returns members of the committee
 * Input: committeeId*
 * Output: {@link CommitteeMembers}
 *
 * =========== EXAMPLE USAGE ========
 *
 * CommitteeClass committeeClass = new CommitteeClass();
 *
 * Committee committee = committeeClass.getCommittee(committeeByBio.committeeId);
 *
 * CommitteeTypes committeeTypes = committeeClass.getTypes();
 * </pre>
 *
 */
public class CommitteeClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public CommitteeClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public CommitteeClass() throws VoteSmartException {
		super();
	}

	/**
	 * Returns the committee types(house, senate, joint, etc)
	 *
	 * @return {@link CommitteeTypes}:
	 */
	public CommitteeTypes getTypes() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Committee.getTypes", null, CommitteeTypes.class );
	}

	/**
	 * Returns the list of committees that fit the criteria.
	 *
	 * @return {@link Committees}:
	 */
	public Committees getCommitteesByTypeState() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Committee.getCommitteesByTypeState", null, Committees.class );
	}

	/**
	 * Returns the list of committees that fit the criteria.
	 *
	 * @param typeId
	 * @return {@link Committees}:
	 */
	public Committees getCommitteesByTypeState(String typeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Committee.getCommitteesByTypeState", new ArgMap("typeId", typeId), Committees.class );
	}

	/**
	 * Returns the list of committees that fit the criteria.
	 *
	 * @param typeId
	 * @param stateId
	 * @return {@link Committees}:
	 */
	public Committees getCommitteesByTypeState(String typeId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Committee.getCommitteesByTypeState", new ArgMap("typeId", typeId, "stateId", stateId), Committees.class );
	}

	/**
	 * Returns detailed committee data.
	 *
	 * @param committeeId
	 * @return {@link Committee}:
	 */
	public Committee getCommittee(String committeeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Committee.getCommittee", new ArgMap("committeeId", committeeId), Committee.class );
	}

	/**
	 * Returns members of the committee.
	 *
	 * @param committeeId
	 * @return {@link CommitteeMembers}:
	 */
	public CommitteeMembers getCommitteeMembers(String committeeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Committee.getCommitteeMembers", new ArgMap("committeeId", committeeId), CommitteeMembers.class );
	}
}


package org.votesmart.classes;

import org.votesmart.api.*;
import org.votesmart.data.Leaders;
import org.votesmart.data.Leadership;

/**
 * <pre>
 * Leadership Class
 *
 * * - Required
 * * - Multiple rows
 *
 * Leadership.getPositions()
 * Gets leadership positions by state and office
 * Input: stateId(default: 'NA'), officeId(default: All)
 * Output: {@link Leadership}
 *
 * Leadership.getOfficials()
 * Gets officials that hold the leadership role in certain states.
 * Input: leadershipId*, stateId(default: 'NA')
 * Output: {@link Leaders}
 *
 * ============== EXAMPLE USAGE =============
 *
 * // Leadership class
 * LeadershipClass leadershipClass = new LeadershipClass();
 *
 * Leadership leadership = leadershipClass.getPositions();
 *
 * // all positions
 * leadership = leadershipClass.getPositions(state.stateId);
 *
 * // all positions for office in state
 * leadership = leadershipClass.getPositions(state.stateId, office.officeId);
 * Leadership.Position position = leadership.position.get(0);
 * </pre>
 *
 */
public class LeadershipClass extends ClassesBase {

	/**
	 * Constructor for testing purposes.
	 *
	 * @param api
	 */
	public LeadershipClass(VoteSmartAPI api) {
		super(api);
	}

	/**
	 * Default Constructor
	 */
	public LeadershipClass() throws VoteSmartException {
		super();
	}

	/**
	 * Gets leadership positions by state and office.
	 *
	 * @return {@link Leadership}:
	 */
	public Leadership getPositions() throws VoteSmartException, VoteSmartErrorException {
		return api.query("Leadership.getPositions", new ArgMap(), Leadership.class );
	}

	/**
	 * Gets leadership positions by state and office.
	 *
	 * @param stateId
	 * @return {@link Leadership}:
	 */
	public Leadership getPositions(String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Leadership.getPositions", new ArgMap("stateId", stateId), Leadership.class );
	}

	/**
	 * Gets leadership positions by state and office.
	 *
	 * @param stateId
	 * @param officeId
	 * @return {@link Leadership}:
	 */
	public Leadership getPositions(String stateId, String officeId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Leadership.getPositions", new ArgMap("stateId", stateId, "officeId", officeId), Leadership.class );
	}

	/**
	 * Gets officials that hold the leadership role in certain states.
	 *
	 * @param leadershipId
	 * @return {@link Leaders}:
	 */
	public Leaders getOfficials(String leadershipId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Leadership.getOfficials", new ArgMap("leadershipId", leadershipId), Leaders.class );
	}

	/**
	 * Gets officials that hold the leadership role in certain states.
	 *
	 * @param leadershipId
	 * @param stateId
	 * @return {@link Leaders}:
	 */
	public Leaders getOfficials(String leadershipId, String stateId) throws VoteSmartException, VoteSmartErrorException {
		return api.query("Leadership.getOfficials", new ArgMap("leadershipId", leadershipId, "stateId", stateId), Leaders.class );
	}
}