/* * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. * * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM */ package org.csstudio.dal.group; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.log4j.Logger; import org.csstudio.dal.DynamicValueProperty; import com.cosylab.util.ListenerList; /** * PropertyCollection implementation based on HashMap. * * @author Igor Kriznar (igor.kriznarATcosylab.com) * * @param <T> exct type of properties */ public class PropertyCollectionMap<T extends DynamicValueProperty<?>> implements PropertyCollection<T> { class PIterator<Tt> implements Iterator<Tt> { private Iterator<Tt[]> it; private Tt[] elements; private int i=0; public PIterator(Iterator<Tt[]> it) { this.it=it; } @Override public boolean hasNext() { return (elements!=null && elements.length>i) || it.hasNext(); } @Override public Tt next() { if (elements!=null) { if (i<elements.length) { return elements[i++]; } else { elements=null; return next(); } } elements= it.next(); i=0; return next(); } @Override public void remove() { throw new UnsupportedOperationException(); } } protected Class<T> type; protected ListenerList groupListeners; protected Map<String, T[]> properties; private int size=0; private T[] zero_length; /** * */ public PropertyCollectionMap(Class<T> cl) { super(); this.type=cl; properties = new HashMap<String, T[]>(); zero_length= (T[])Array.newInstance(type, 0); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#size() */ @Override public int size() { return size; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#isEmpty() */ @Override public boolean isEmpty() { return properties.isEmpty(); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#contains(java.lang.Object) */ @Override public boolean contains(Object property) { if (property==null) { return false; } if (type.isAssignableFrom(property.getClass())) { T[] t= get(((T)property).getName()); if (t!=null) { for (int i = 0; i < t.length; i++) { if (t[i]==property) { return true; } } } } return false; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#iterator() */ @Override public Iterator<T> iterator() { return new PIterator<T>(properties.values().iterator()); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#toArray() */ @Override public Object[] toArray() { return toPropertyArray(); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#toPropertyArray() */ @Override public T[] toPropertyArray() { T[] t= (T[])Array.newInstance(type, size); Iterator<T> it= iterator(); for (int i = 0; i < t.length; i++) { t[i]=it.next(); } return t; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#toArray(E[]) */ @Override public <E extends T> E[] toArray(E[] array) { ArrayList<E> l= new ArrayList<E>(size); for (T t : this) { if (array.getClass().getComponentType().isAssignableFrom(t.getClass())) { l.add((E)t); } } return l.toArray(array); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#containsAll(java.util.Collection) */ @Override public boolean containsAll(Collection<?> colection) { for (Object p : colection) { if (!contains(p)) { return false; } } return true; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#contains(java.lang.String) */ @Override public boolean contains(String name) { return properties.containsKey(name); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#contains(java.lang.String) */ @Override public boolean contains(String name, Class<? extends T> type) { return getFirst(name, type)!=null; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#get(java.lang.String) */ @Override public T[] get(String name) { T[] t= properties.get(name); if (t==null) { return zero_length; } return t; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#get(java.lang.String) */ @Override public <A extends T> A[] get(String name, Class<A> type) { T[] t= get(name); if (t==null) { return (A[])Array.newInstance(type, 0); } ArrayList<A> l= new ArrayList<A>(t.length); for (int i = 0; i < t.length; i++) { if (type.isAssignableFrom(t[i].getClass())) { l.add((A)t[i]); } } return l.toArray((A[])Array.newInstance(type, l.size())); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#get(java.lang.String) */ @Override public T getFirst(String name) { T[] t=properties.get(name); if (t != null && t.length>0) { return t[0]; } return null; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#get(java.lang.String) */ @Override public <A extends T> A getFirst(String name, Class<A> type) { T[] t= get(name); if (t!=null && t.length>0) { for (int i = 0; i < t.length; i++) { if (type.isAssignableFrom(t[i].getClass())) { return (A)t[i]; } } } return null; } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#getPropertyNames() */ @Override public String[] getPropertyNames() { return (String[])properties.keySet().toArray(); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#addGroupListner(org.csstudio.dal.group.GroupListener) */ @Override public void addPropertyGroupListner(PropertyGroupListener<T> l) { if (groupListeners == null) { groupListeners = new ListenerList(PropertyGroupListener.class); } groupListeners.add(l); } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#removeGroupListner(org.csstudio.dal.group.GroupListener) */ @Override public void removePropertyGroupListner(PropertyGroupListener<T> l) { if (groupListeners != null) { groupListeners.remove(l); } } /* (non-Javadoc) * @see org.csstudio.dal.group.PropertyCollection#getGroupListners() */ @Override public PropertyGroupListener<T>[] getPropertyGroupListners() { if (groupListeners != null) { return (PropertyGroupListener<T>[])groupListeners.toArray(); } return new PropertyGroupListener[0]; } protected void fireGroupEvent(PropertyGroupEvent<T> event, boolean added) { if (groupListeners == null) { return; } PropertyGroupListener<T>[] l = (PropertyGroupListener<T>[])groupListeners.toArray(); if (added) { for (int i = 0; i < l.length; i++) { try { l[i].membersAdded(event); } catch (Exception e) { Logger.getLogger(PropertyCollectionMap.class).warn("Error in event handler, continuing.", e); } } } else { for (int i = 0; i < l.length; i++) { try { l[i].membersRemoved(event); } catch (Exception e) { Logger.getLogger(PropertyCollectionMap.class).warn("Error in event handler, continuing.", e); } } } } /* * @see MutablePropertyCollection#add(T) */ protected void add(T property) { String name= ((DynamicValueProperty<?>)property).getName(); T[] t = (T[])Array.newInstance(type, 1); t[0] = property; T[] p= get(property.getName()); if (p==null||p.length==0) { properties.put(name, t); } else { T[] pp = (T[])Array.newInstance(type, p.length+1); System.arraycopy(p, 0, pp, 0, p.length); pp[p.length]=property; properties.put(name, pp); } size++; fireGroupEvent(new PropertyGroupEvent<T>(this, t), true); } /* * @see MutablePropertyCollection#remove(T) */ protected void remove(T property) { T[] t= get(property.getName()); if (t==null || t.length==0) { return; } for (int i = 0; i < t.length; i++) { if (property==t[i]) { if (t.length==1) { properties.remove(property.getName()); } else { T[] pp= (T[])Array.newInstance(type, t.length-1); System.arraycopy(t, 0, pp, 0, i); System.arraycopy(t, i+1, pp, i, t.length-1-i); properties.put(property.getName(), pp); } } } size--; t = (T[])Array.newInstance(property.getClass(), 1); t[0] = property; fireGroupEvent(new PropertyGroupEvent<T>(this, t), false); } protected void clear() { properties.clear(); } } /* __oOo__ */