001    package edu.nrao.sss.clipboard;
002    
003    import java.lang.reflect.Method;
004    import java.lang.reflect.InvocationTargetException;
005    import java.util.List;
006    import java.util.ArrayList;
007    import java.util.Collection;
008    
009    /**
010     * This ClipBoard will hold a Collection of Cloneable objects. Objects are
011     * retrieved from the ClipBoard by passing the getContents() method a Class
012     * object representing the type of objects you want to get out. calling
013     * setContentItem or setContentItems will remove any previous ClipBoard
014     * contents. All items put into the clip board must implement cloneable. Items
015     * are cloned when they are inserted into the ClipBoard and cloned
016     * <em>again</em> when they are retrieved. All methods in this class are
017     * synchronized.
018     */
019    public class ClipBoard
020    {
021            private List<Cloneable> contents;
022    
023            public ClipBoard()
024            {
025                    this.contents = new ArrayList<Cloneable>();
026            }
027    
028            public synchronized boolean isEmpty()
029            {
030                    return this.contents.isEmpty();
031            }
032    
033            public synchronized void clear()
034            {
035                    this.contents.clear();
036            }
037    
038            public synchronized List<Cloneable> getContents()
039            {
040                    List<Cloneable> ret = new ArrayList<Cloneable>();
041                    for (Cloneable item : this.contents)
042                            addCloneTo(Cloneable.class, item, ret);
043    
044                    return ret;
045            }
046    
047            @SuppressWarnings("unchecked")
048            public synchronized <T extends Cloneable> List<T> getContents(Class<T> c)
049            {
050                    List<T> ret = new ArrayList<T>();
051    
052                    for (Cloneable item : this.contents)
053                    {
054                            if (c.isInstance(item))
055                            {
056                                    addCloneTo(c, (T)item, ret);
057                            }
058                    }
059    
060                    return ret;
061            }
062    
063            public synchronized boolean containsType(Class<?> c)
064            {
065                    for (Cloneable item : this.contents)
066                    {
067                            if (c.isInstance(item))
068                            {
069                                    return true;
070                            }
071                    }
072    
073                    return false;
074            }
075    
076            public synchronized void setContentItems(Collection<Cloneable> items)
077                    throws IllegalArgumentException
078            {
079                    clear();
080                    addContentItems(items);
081            }
082    
083            public synchronized void setContentItem(Cloneable item)
084                    throws IllegalArgumentException
085            {
086                    clear();
087                    addCloneTo(Cloneable.class, item, this.contents);
088            }
089    
090            public synchronized void addContentItems(Collection<Cloneable> items)
091                    throws IllegalArgumentException
092            {
093                    for (Cloneable item : items)
094                            addCloneTo(Cloneable.class, item, this.contents);
095            }
096    
097            public synchronized void addContentItem(Cloneable item)
098                    throws IllegalArgumentException
099            {
100                    addCloneTo(Cloneable.class, item, this.contents);
101            }
102    
103            @SuppressWarnings("unchecked")
104            private synchronized <T extends Cloneable> void addCloneTo(Class<T> cls, T item, List<T> destination)
105                    throws IllegalArgumentException
106            {
107                    if (item == null || destination == null)
108                            throw new IllegalArgumentException("Arguments can not be null!");
109    
110                    T copy = null;
111                    try
112                    {
113                            //Do a clone of item and add it to destination
114                            Class c = item.getClass();
115                            Method m = c.getMethod("clone", new Class[0]);
116                            copy = (T)m.invoke(item, new Object[0]);
117                    }
118    
119                    catch (IllegalAccessException e)
120                    {
121                            throw new IllegalArgumentException("Cannot add item to clipboard", e);
122                    }
123    
124                    catch (NoSuchMethodException e)
125                    {
126                            throw new IllegalArgumentException("Cannot add item to clipboard", e);
127                    }
128    
129                    catch (InvocationTargetException e)
130                    {
131                            throw new IllegalArgumentException("Cannot add item to clipboard", e);
132                    }
133    
134                    catch (NullPointerException e)
135                    {
136                            throw new IllegalArgumentException("Cannot add item to clipboard", e);
137                    }
138    
139                    catch (ExceptionInInitializerError e)
140                    {
141                            throw new IllegalArgumentException("Cannot add item to clipboard", e);
142                    }
143    
144                    if (copy != null)
145                    {
146                            destination.add(copy);
147                    }
148            }
149    }