package ini.trakem2.utils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** Classes extending this class acquire a read-only Map interface to access its declared fields * via the reflection API provided by {@link Class#getDeclaredFields()} and {@link Field}. * Fields of superclasses are not included. */ public class FieldMapView implements Map<String,String> { @Override public int size() { return getClass().getDeclaredFields().length; } @Override public boolean isEmpty() { return 0 != size(); } /** Linear search. * @param key A {@link String}. Can be null. Tests for field names with {@link Object#equals(Object)}. */ @Override public boolean containsKey(final Object key) { if (null == key) return false; for (final Field field : getClass().getDeclaredFields()) { if (field.getName().equals(key)) return true; } return false; } /** Linear search. * @param value A {@link String}. Can be null. Tests for field values with {@link Object#equals(Object)}. */ @Override public boolean containsValue(final Object value) { if (null == value) return false; for (final Field field : getClass().getDeclaredFields()) { field.setAccessible(true); try { if (field.get(this).equals(value)) return true; } catch (Exception e) { throw new RuntimeException(e); } } return false; } /** Linear search. * @param key A {@link String}. Can be null. Tests for field names with {@link Object#equals(Object)}. * @return A {@link String} representation of the field named by {@code key}. */ @Override public String get(final Object key) { if (null == key) return null; for (final Field field : getClass().getDeclaredFields()) { if (field.getName().equals(key)) { field.setAccessible(true); try { return field.get(this).toString(); } catch (Exception e) { e.printStackTrace(); return null; } } } return null; } /** * @throws UnsupportedOperationException */ @Override public String put(String key, String value) { throw new UnsupportedOperationException(); } /** * @throws UnsupportedOperationException */ @Override public String remove(Object key) { throw new UnsupportedOperationException(); } /** * @throws UnsupportedOperationException */ @Override public void putAll(Map<? extends String, ? extends String> m) { throw new UnsupportedOperationException(); } /** * @throws UnsupportedOperationException */ @Override public void clear() { throw new UnsupportedOperationException(); } /** * @return An unmodifiable {@link Set} as created by {@link Collections#unmodifiableSet(Set)}. */ @Override public Set<String> keySet() { final HashSet<String> hs = new HashSet<String>(size()); for (final Field field : getClass().getDeclaredFields()) { hs.add(field.getName()); } return Collections.unmodifiableSet(hs); } /** * @return An unmodifiable {@link List} as created by {@link Collections#unmodifiableList(List)}. */ @Override public Collection<String> values() { final ArrayList<String> vals = new ArrayList<String>(size()); for (final Field field : getClass().getDeclaredFields()) { field.setAccessible(true); try { vals.add(field.get(this).toString()); } catch (Exception e) { e.printStackTrace(); } } return Collections.unmodifiableList(vals); } /** * @return An unmodifiable {@link Set} as created by {@link Collections#unmodifiableSet(Set)} of unmodifiable entries. */ @Override public Set<Map.Entry<String, String>> entrySet() { final HashSet<Map.Entry<String,String>> entries = new HashSet<Map.Entry<String,String>>(size()); for (final Field field : getClass().getDeclaredFields()) { field.setAccessible(true); entries.add(new Map.Entry<String,String>() { @Override public String getKey() { return field.getName(); } @Override public String getValue() { try { return field.get(FieldMapView.this).toString(); } catch (Exception e) { throw new RuntimeException(e); } } @Override public String setValue(String value) { throw new UnsupportedOperationException(); } }); } return Collections.unmodifiableSet(entries); } }