/* * This file is part of Alida, a Java library for * Advanced Library for Integrated Development of Data Analysis Applications. * * Copyright (C) 2010 - @YEAR@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Fore more information on Alida, visit * * http://www.informatik.uni-halle.de/alida/ * */ package de.unihalle.informatik.Alida.dataio.provider.swing; import de.unihalle.informatik.Alida.annotations.ALDDataIOProvider; import de.unihalle.informatik.Alida.dataio.provider.ALDDataIOSwing; import de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent; import de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponentCheckBox; import de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponentLabel; import de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponentTextField; import de.unihalle.informatik.Alida.exceptions.ALDDataIOProviderException; import de.unihalle.informatik.Alida.exceptions.ALDDataIOProviderException.ALDDataIOProviderExceptionType; import de.unihalle.informatik.Alida.helpers.ALDParser; import de.unihalle.informatik.Alida.operator.ALDParameterDescriptor; import javax.swing.*; import java.lang.reflect.Field; import java.util.Collection; import java.util.LinkedList; /** * Class for loading/saving primitive datatypes in Alida. * * @author moeller * */ @ALDDataIOProvider public class ALDNativeDataIOSwing implements ALDDataIOSwing { /** * Interface method to announce class for which IO is provided for. * * @return Collection of classes provided. */ @Override public Collection<Class<?>> providedClasses() { LinkedList<Class<?>> classes = new LinkedList<Class<?>>(); classes.add( String.class); classes.add( boolean.class); classes.add( byte.class); classes.add( double.class); classes.add( float.class); classes.add( int.class); classes.add( long.class); classes.add( short.class); classes.add( Boolean.class); classes.add( Byte.class); classes.add( Double.class); classes.add( Float.class); classes.add( Integer.class); classes.add( Long.class); classes.add( Short.class); return classes; } @Override public Object getInitialGUIValue(Field field, Class<?> cl, Object obj, ALDParameterDescriptor descr) throws ALDDataIOProviderException { // info strings are just shown in a label if (cl.equals(String.class) && descr != null && descr.isInfo()) { if (obj == null) return new ALDSwingComponentLabel(""); return this.reformatInfoString(obj.toString()); } // all data types except booleans if ( cl != boolean.class && cl != Boolean.class ) { if ( obj != null ) return obj; return this.getDummyInitializer(cl); } // handling of booleans, if no value is provided, checkbox will // initially be unselected if ( obj != null ) return obj; return new Boolean(false); } @Override public ALDSwingComponent createGUIElement(Field field, Class<?> cl, Object obj, ALDParameterDescriptor descr) throws ALDDataIOProviderException { // info strings are just shown in a label if (cl.equals(String.class) && descr != null && descr.isInfo()) { if (obj == null) return new ALDSwingComponentLabel(""); return new ALDSwingComponentLabel( this.reformatInfoString(obj.toString())); } // all data types except booleans if ( cl != boolean.class && cl != Boolean.class ) { ALDSwingComponentTextField textfield= new ALDSwingComponentTextField(cl, descr, 25); if ( obj != null ) { if ( supported1DArray( cl) ) { textfield.setText( ALDParser.arrayToString( obj)); } else { textfield.setText( obj.toString()); } } else { // fill textfield with default value Object dummyObject = this.getDummyInitializer(cl); textfield.setText(dummyObject.toString()); } return textfield; } // handling of booleans ALDSwingComponentCheckBox checkbox = new ALDSwingComponentCheckBox(descr); if ( obj != null ) checkbox.getJComponent().setSelected( ((Boolean)obj).booleanValue()); return checkbox; } /** * Method to instantiate dummy object of requested class for default. * @param cl Class of parameter object. * @return Returns object of requested class set to default value. * @throws ALDDataIOProviderException Thrown if class is not supported. */ private Object getDummyInitializer(Class<?> cl) throws ALDDataIOProviderException { if (cl.equals(String.class)) return new String(); if (cl.equals(byte.class) || cl.equals(Byte.class)) { return new Byte((byte)0); } if (cl.equals(double.class) || cl.equals(Double.class)) { return new Double(0); } if (cl.equals(float.class) || cl.equals(Float.class)) { return new Float(0); } if (cl.equals(int.class) || cl.equals(Integer.class)) { return new Integer(0); } if (cl.equals(long.class) || cl.equals(Long.class)) { return new Long(0); } if (cl.equals(short.class) || cl.equals(Short.class)) { return new Short((short)0); } throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.UNSPECIFIED_ERROR, "[ALDNativeDataIOSwing::getDummyInitializer] got request for " + "unsupported class <" + cl.getName() + ">..."); } @Override public void setValue(Field field, Class<?> cl, ALDSwingComponent guiElement, Object value) throws ALDDataIOProviderException { // info strings if (guiElement instanceof ALDSwingComponentLabel) { String newString = this.reformatInfoString(value.toString()); ((ALDSwingComponentLabel)guiElement).getJComponent().setText( newString); return; } // all other classes except boolean if ( cl != boolean.class && cl != Boolean.class ) { if (!(guiElement instanceof ALDSwingComponentTextField)) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.INVALID_GUI_ELEMENT, "NativeDataIO: readData received invalid GUI element!"); // 2D-arrays if (cl.getName().startsWith("[[")) { throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.UNSPECIFIED_ERROR, "ALDNativeDataIO: 2D array reading not available!"); } if (value == null) { ((ALDSwingComponentTextField)guiElement).setText( this.getDummyInitializer(cl).toString()); } else { ((ALDSwingComponentTextField)guiElement).setText( new String(value.toString())); } } else { // handle booleans if (value == null) { // set to default ((ALDSwingComponentCheckBox)guiElement).getJComponent(). setSelected(false); } else ((ALDSwingComponentCheckBox)guiElement).getJComponent(). setSelected(((Boolean)value).booleanValue()); } } @Override public Object readData( Field field, Class<?> cl, ALDSwingComponent guiElement) throws ALDDataIOProviderException { // ignore info strings if (guiElement instanceof ALDSwingComponentLabel) { return ((ALDSwingComponentLabel)guiElement).getJComponent().getText(); } if ( cl != boolean.class && cl != Boolean.class ) { if (!(guiElement instanceof ALDSwingComponentTextField)) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.INVALID_GUI_ELEMENT, "NativeDataIO: readData received invalid GUI element!"); String text = ((ALDSwingComponentTextField)guiElement).getText(); // if there are no contents in the text field, we have a problem... if (text.isEmpty() && !(cl.equals(String.class))) return null; if (cl.equals(String.class)) return text; try { // native types if (cl.equals(boolean.class)) return Boolean.valueOf(text); if (cl.equals(byte.class)) return Byte.valueOf(text); if (cl.equals(double.class)) return Double.valueOf(text); if (cl.equals(float.class)) return Float.valueOf(text); if (cl.equals(int.class)) return Integer.valueOf(text); if (cl.equals(long.class)) return Long.valueOf(text); if (cl.equals(short.class)) return Short.valueOf(text); // wrapper if (cl.equals(Boolean.class)) return Boolean.valueOf(text); if (cl.equals(Byte.class)) return Byte.valueOf(text); if (cl.equals(Double.class)) return Double.valueOf(text); if (cl.equals(Float.class)) return Float.valueOf(text); if (cl.equals(Integer.class)) return Integer.valueOf(text); if (cl.equals(Long.class)) return Long.valueOf(text); if (cl.equals(Short.class)) return Short.valueOf(text); // 2D-arrays if (cl.getName().startsWith("[[")) { throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.UNSPECIFIED_ERROR, "ALDNativeDataIO: 2D array reading not available!"); } // // 1D-arrays // else if ( supported1DArray( cl) ) { // return ALDParser.readArray1D(cl, text); // } } catch (Exception e) { throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.UNSPECIFIED_ERROR, "ALDNativeDataIO: something went wrong in parsing..." + e.getMessage()); } } else { if (!(guiElement instanceof ALDSwingComponentCheckBox)) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.INVALID_GUI_ELEMENT, "NativeDataIO: readData received invalid GUI element!"); return new Boolean(((ALDSwingComponentCheckBox)guiElement). getJComponent().isSelected()); } // we should never end up here throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.UNSPECIFIED_ERROR, "ALDNativeDataIOSwing - something went wrong, " + "I don't know what..."); } @Override public JComponent writeData(Object obj, ALDParameterDescriptor descr) throws ALDDataIOProviderException { if (obj == null) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.UNSPECIFIED_ERROR, "[ALDNativeDataIOSwing::writeData()] received null object!"); // info strings if (obj.getClass() == String.class && descr.isInfo()) { return new JLabel(this.reformatInfoString(obj.toString())); } if ( obj.getClass() != boolean.class && obj.getClass() != Boolean.class ) { JTextField textfield = new JTextField(25); if ( supported1DArray( obj.getClass()) ) textfield.setText( ALDParser.arrayToString( obj)); else textfield.setText( obj.toString()); textfield.setEditable( false); return textfield; } JCheckBox checkbox = new JCheckBox(); checkbox.setSelected( ((Boolean)obj).booleanValue() ); checkbox.setEnabled( false); return checkbox; } /** * Checks if a given class is supported or not. * * @param cl Class to check. * @return True if class is supported. */ private boolean supported1DArray( Class<?> cl ) { if ( cl == Boolean[].class || cl == Byte[].class || cl == Double[].class || cl == Float[].class || cl == Integer[].class || cl == Short[].class || cl == String[].class || cl == boolean[].class || cl == byte[].class || cl == double[].class || cl == float[].class || cl == int[].class || cl == short[].class) return true; return false; } /** * Reformats an info message to multiple lines if it contains newlines. * @param infoMsg Message to reformat. * @return Reformatted string. */ private String reformatInfoString(String infoMsg) { String newInfoMsg = infoMsg; if (infoMsg.contains("<html>")) return newInfoMsg; else if (infoMsg.contains("\n")) { newInfoMsg = "<html>" + infoMsg.replace("\n", "<br>") + "</html>"; } else { newInfoMsg = "<html>" + infoMsg + "</html>"; } return newInfoMsg; } }