package games.strategy.engine.data.properties; import java.awt.Color; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.swing.JComponent; /** * Basically creates a map of other properties. * * @param <T> * String or something with a valid toString() * @param <U> * parameters can be: Boolean, String, Integer, Double, Color, File, Collection, Map */ public class MapProperty<T, U> extends AEditableProperty { private static final long serialVersionUID = -8021039503574228146L; private Map<T, U> m_map; final List<IEditableProperty> m_properties = new ArrayList<>(); public MapProperty(final String name, final String description, final Map<T, U> map) { super(name, description); m_map = map; resetProperties(map, m_properties, name, description); } @SuppressWarnings("unchecked") private void resetProperties(final Map<T, U> map, final List<IEditableProperty> properties, final String name, final String description) { properties.clear(); for (final Entry<T, U> entry : map.entrySet()) { final String key = (String) entry.getKey(); final U value = entry.getValue(); if (value instanceof Boolean) { properties.add(new BooleanProperty(key, description, ((Boolean) value))); } else if (value instanceof Color) { properties.add(new ColorProperty(key, description, ((Color) value))); } else if (value instanceof File) { properties.add(new FileProperty(key, description, ((File) value))); } else if (value instanceof String) { properties.add(new StringProperty(key, description, ((String) value))); } else if (value instanceof Collection || value instanceof List || value instanceof Set) { properties.add(new CollectionProperty<>(name, description, ((Collection<U>) value))); } else if (value instanceof Integer) { properties.add(new NumberProperty(key, description, Integer.MAX_VALUE, Integer.MIN_VALUE, ((Integer) value))); } else if (value instanceof Double) { properties.add(new DoubleProperty(key, description, Double.MAX_VALUE, Double.MIN_VALUE, ((Double) value), 5)); } else { throw new IllegalArgumentException( "Cannot instantiate MapProperty with: " + value.getClass().getCanonicalName()); } } } @Override public int getRowsNeeded() { return Math.max(1, m_properties.size()); } @Override public Object getValue() { return m_map; } public Map<T, U> getValueT() { return m_map; } @Override @SuppressWarnings("unchecked") public void setValue(final Object value) throws ClassCastException { m_map = (Map<T, U>) value; resetProperties(m_map, m_properties, this.getName(), this.getDescription()); } public void setValueT(final Map<T, U> value) { m_map = value; resetProperties(m_map, m_properties, this.getName(), this.getDescription()); } @Override public JComponent getEditorComponent() { final PropertiesUI ui = new PropertiesUI(m_properties, true); return ui; } @Override public JComponent getViewComponent() { final PropertiesUI ui = new PropertiesUI(m_properties, false); return ui; } @Override public boolean validate(final Object value) { if (value == null) { // is this ok? no idea, no maps or anything use this return false; } if (Map.class.isAssignableFrom(value.getClass())) { try { @SuppressWarnings("unchecked") final Map<T, U> test = (Map<T, U>) value; if (m_map != null && !m_map.isEmpty() && test != null && !test.isEmpty()) { T key = null; U val = null; for (final Entry<T, U> entry : m_map.entrySet()) { if (entry.getValue() != null && entry.getKey() != null) { key = entry.getKey(); val = entry.getValue(); break; } } if (key != null && val != null) { for (final Entry<T, U> entry : test.entrySet()) { if (entry.getKey() != null && entry.getValue() != null && (!entry.getKey().getClass().isAssignableFrom(key.getClass()) || !entry.getValue().getClass().isAssignableFrom(val.getClass()))) { return false; } } } } final List<IEditableProperty> testProps = new ArrayList<>(); resetProperties(test, testProps, this.getName(), this.getDescription()); } catch (final Exception e) { return false; } return true; } return false; } }