r1091 - in lutinjaxx/trunk/jaxx-core/src: main/java/jaxx/runtime main/java/jaxx/runtime/swing test/java/jaxx/runtime
Author: tchemit Date: 2008-12-23 10:35:41 +0000 (Tue, 23 Dec 2008) New Revision: 1091 Added: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/DecoratorTableCellRenderer.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellRenderer.java Removed: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java Log: - fix parent context search bug : if a nmae is given, use it. - improve comparator in JXPathDecorator, no more redondant datas - make works I18nCellRenderer when the position of column has changed Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java 2008-12-23 10:31:56 UTC (rev 1090) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -50,7 +50,7 @@ } public <T> void setContextValue(T o, String name) { - if (PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { + if (name == null && PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { setParentContext((JAXXContext) o); return; } Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java 2008-12-23 10:31:56 UTC (rev 1090) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -1,18 +1,16 @@ package jaxx.runtime; -import org.apache.commons.beanutils.MethodUtils; -import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.beans.PropertyDescriptor; -import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * JXPath decorator based on {@link String#format(String, Object[])} method. @@ -67,11 +65,55 @@ * @param datas the list of data to sort * @param pos the index of context to used in decorator to obtain sorted property. */ - public static void sort(JXPathDecorator decorator, List<?> datas, int pos) { - Collections.sort(datas, decorator.getComparator(pos)); + public static <O> void sort(JXPathDecorator<O> decorator, List<O> datas, int pos) { + Comparator<O> c = decorator.getComparator(pos); + boolean cachedComparator = c instanceof JXPathComparator; + try { + if (cachedComparator) { + ((JXPathComparator<O>) c).init(decorator, datas); + } + Collections.sort(datas, c); + } finally { + if (cachedComparator) { + ((JXPathComparator) c).clear(); + } + } } - protected static class Context implements Serializable { + public static class JXPathComparator<O> implements Comparator<O> { + + protected Map<O, Comparable<Comparable>> valueCache; + + private final String expression; + + public JXPathComparator(String expression) { + this.expression = expression; + this.valueCache = new HashMap<O, Comparable<Comparable>>(); + } + + @Override + public int compare(O o1, O o2) { + Comparable<Comparable> c1 = valueCache.get(o1); + Comparable<Comparable> c2 = valueCache.get(o2); + return c1.compareTo(c2); + } + + public void clear() { + valueCache.clear(); + } + + public void init(JXPathDecorator<O> decorator, List<O> datas) { + clear(); + for (O data : datas) { + JXPathContext jxcontext = JXPathContext.newContext(data); + Comparable<Comparable> key = decorator.getTokenValue(jxcontext, expression); + valueCache.put(data, key); + } + } + } + + public static class Context<O> implements java.io.Serializable { + /** * expression to format using {@link String#format(String, Object[])}, all variables are compute * using using the jxpath tokens. @@ -81,7 +123,7 @@ /** list of jxpath tokens to apply on expression */ protected String[] tokens; - protected transient Comparator comparator; + protected transient Comparator<O> comparator; private static final long serialVersionUID = 1L; @@ -94,62 +136,15 @@ return tokens[0]; } - public Comparator getComparator(JXPathDecorator decorator, int pos) { + public Comparator<O> getComparator(int pos) { if (comparator == null) { - - final String property = tokens[pos]; - - Class<?> type = getType(decorator, pos); - - // does not work with javassist, a shame... - //Comparator<?> comparator = new BeanComparator(property); - - if (Number.class.isAssignableFrom(type) || Comparable.class.isAssignableFrom(type)) { - comparator = new Comparator() { - public int compare(Object o1, Object o2) { - Comparable c1 = getValue(o1); - Comparable c2 = getValue(o2); - return c1.compareTo(c2); - } - - public Comparable<Comparable> getValue(Object o) { - try { - Object r = PropertyUtils.getProperty(o, property); - return (Comparable) r; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - }; - } - if (comparator == null) { - throw new IllegalStateException("could not find comparator for type " + type); - } - //todo fixme add a default comparator basedon toString() comparator ? - return comparator; + comparator = new JXPathComparator<O>(tokens[pos]); } return comparator; } - protected Class<?> getType(JXPathDecorator decorator, int pos) { - ensureTokenIndex(decorator, pos); - - String property = getFirstProperty(); - - if (property == null) { - throw new NullPointerException("could not find property in " + this); - } - - for (PropertyDescriptor descriptor : decorator.getDescriptors()) { - if (property.equals(descriptor.getName())) { - Class<?> type = descriptor.getReadMethod().getReturnType(); - if (type.isPrimitive()) { - type = MethodUtils.getPrimitiveWrapper(type); - } - return type; - } - } - throw new IllegalStateException("could not find read method for property " + property); + public void setComparator(Comparator<O> comparator) { + this.comparator = comparator; } @Override @@ -159,7 +154,7 @@ } /** the computed context of the decorator */ - protected Context context; + protected Context<O> context; /** nb jxpath tokens to compute */ protected int nbToken; @@ -167,9 +162,6 @@ /** the initial expression used to compute the decorator context. */ protected String initialExpression; - /** cache of descriptors of the internal class (used for sorting) */ - protected transient PropertyDescriptor[] descriptors; - public String toString(Object bean) { if (bean == null) { return null; @@ -177,11 +169,17 @@ JXPathContext jxcontext = JXPathContext.newContext(bean); Object[] args = new Object[nbToken]; for (int i = 0; i < nbToken; i++) { - args[i] = jxcontext.getValue(context.tokens[i]); + args[i] = getTokenValue(jxcontext, context.tokens[i]); } return String.format(context.expression, args); } + @SuppressWarnings({"unchecked"}) + protected Comparable<Comparable> getTokenValue(JXPathContext jxcontext, String token) { + // assume all values are comparable + return (Comparable<Comparable>) jxcontext.getValue(token); + } + public String getProperty(int pos) { return getTokens()[pos]; } @@ -207,14 +205,7 @@ return super.toString() + "<" + context + ">"; } - public PropertyDescriptor[] getDescriptors() { - if (descriptors == null) { - descriptors = PropertyUtils.getPropertyDescriptors(internalClass); - } - return descriptors; - } - - public void setContext(Context context) { + public void setContext(Context<O> context) { this.context = context; this.nbToken = context.tokens.length; // always reset comparator @@ -224,11 +215,11 @@ } } - protected JXPathDecorator(Class<O> internalClass, String expression, boolean creatContext) throws IllegalArgumentException, NullPointerException { + public JXPathDecorator(Class<O> internalClass, String expression, boolean creatContext) throws IllegalArgumentException, NullPointerException { super(internalClass); this.initialExpression = expression; if (creatContext) { - setContext(createInitialContext(expression)); + setContext(JXPathDecorator.<O>createInitialContext(expression)); if (log.isDebugEnabled()) { log.debug(expression + " --> " + this.context); } @@ -238,10 +229,10 @@ @SuppressWarnings({"unchecked"}) protected Comparator<O> getComparator(int pos) { ensureTokenIndex(this, pos); - return context.getComparator(this, pos); + return context.getComparator(pos); } - protected static Context createInitialContext(String expression) { + public static <O> Context<O> createInitialContext(String expression) { List<String> lTokens = new ArrayList<String>(); StringBuilder buffer = new StringBuilder(); int size = expression.length(); @@ -271,7 +262,7 @@ // suffix after end jxpath (or all expression if no jxpath) buffer.append(expression.substring(end + 1)); } - return new Context(buffer.toString(), lTokens.toArray(new String[lTokens.size()])); + return new Context<O>(buffer.toString(), lTokens.toArray(new String[lTokens.size()])); } protected static void ensureTokenIndex(JXPathDecorator decorator, int pos) { Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java 2008-12-23 10:31:56 UTC (rev 1090) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -35,19 +35,19 @@ String separatorReplacement) throws IllegalArgumentException, NullPointerException { - Context[] contexts = createInitialContexts(expression, separator, separatorReplacement); + Context<O>[] contexts = createInitialContexts(expression, separator, separatorReplacement); return new MultiJXPathDecorator<O>(internalClass, expression, separator, separatorReplacement, contexts); } - protected Context[] contexts; + protected Context<O>[] contexts; protected String separator; protected String separatorReplacement; - protected MultiJXPathDecorator(Class<O> internalClass, String expression, - String separator, String separatorReplacement, - Context[] contexts) throws IllegalArgumentException, NullPointerException { + public MultiJXPathDecorator(Class<O> internalClass, String expression, + String separator, String separatorReplacement, + Context<O>[] contexts) throws IllegalArgumentException, NullPointerException { super(internalClass, expression, false); this.separator = separator; this.separatorReplacement = separatorReplacement; @@ -80,13 +80,16 @@ @Override protected Comparator<O> getComparator(int pos) { ensureContextIndex(this, pos); - return contexts[pos].getComparator(this, 0); + Context<O> context1 = contexts[pos]; + return context1.getComparator(0); } - protected static Context[] createInitialContexts(String expression, String separator, String separatorReplacement) { + public static <O> Context<O>[] createInitialContexts(String expression, String separator, String separatorReplacement) { int sep = expression.indexOf(separator); if (sep == -1) { - return new Context[]{createInitialContext(expression)}; + Context<O>[] result = MultiJXPathDecorator.newInstance(1); + result[0] = createInitialContext(expression); + return result; } List<String> tokens = new ArrayList<String>(); @@ -96,7 +99,7 @@ } int nbTokens = tokens.size(); - Context[] contexts = new Context[nbTokens]; + Context<O>[] contexts = newInstance(nbTokens); for (int i = 0; i < nbTokens; i++) { StringBuilder buffer = new StringBuilder(expression.length()); for (int j = 0; j < nbTokens; j++) { @@ -116,4 +119,10 @@ } } + @SuppressWarnings({"unchecked"}) + protected static <O> Context<O>[] newInstance(int size) { + // fixme how to instanciate a typed array with no checking warning ? + return new Context[size]; + } + } \ No newline at end of file Copied: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/DecoratorTableCellRenderer.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java) =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/DecoratorTableCellRenderer.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/DecoratorTableCellRenderer.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -0,0 +1,33 @@ +package jaxx.runtime.swing; + +import jaxx.runtime.Decorator; + +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * A simple TableCellRenderer using a delegate TableCellRenderer to render everything elese thant the text : + * the text is I18nalize. + * + * @author chemit + */ +public class DecoratorTableCellRenderer implements TableCellRenderer { + + /** the delegate cell renderer */ + protected TableCellRenderer delegate; + + protected Decorator decorator; + + public DecoratorTableCellRenderer(TableCellRenderer delegate, Decorator decorator) { + this.delegate = delegate; + this.decorator = decorator; + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { + if (value != null) { + value = decorator.toString(value); + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); + } +} \ No newline at end of file Property changes on: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/DecoratorTableCellRenderer.java ___________________________________________________________________ Name: svn:mergeinfo + Deleted: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java 2008-12-23 10:31:56 UTC (rev 1090) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -1,38 +0,0 @@ -package jaxx.runtime.swing; - -import static org.codelutin.i18n.I18n._; - -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; - -/** - * A simple TableCellRenderer using a delegate TableCellRenderer to render everything elese thant the text : - * the text is I18nalize. - * - * @author chemit - */ -public class I18nTableCellHeaderRenderer implements TableCellRenderer { - - /** the libelles to display */ - protected final String[] keys; - - /** the delegate cell renderer */ - protected TableCellRenderer delegate; - - public I18nTableCellHeaderRenderer(TableCellRenderer delegate, String... keys) { - this.delegate = delegate; - this.keys = keys; - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { - if (column > keys.length) { - throw new IndexOutOfBoundsException("colum can not be greater than " + keys.length); - } - JLabel rendererComponent = (JLabel) delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); - - rendererComponent.setText(_(keys[column])); - return rendererComponent; - } -} Copied: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellRenderer.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java) =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellRenderer.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellRenderer.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -0,0 +1,42 @@ +package jaxx.runtime.swing; + +import static org.codelutin.i18n.I18n._; + +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import java.awt.Component; + +/** + * A simple TableCellRenderer using a delegate TableCellRenderer to render everything elese thant the text : + * the text is I18nalize. + * + * @author chemit + */ +public class I18nTableCellRenderer implements TableCellRenderer { + + /** the libelles to display */ + protected final String[] keys; + + /** the delegate cell renderer */ + protected TableCellRenderer delegate; + + public I18nTableCellRenderer(TableCellRenderer delegate, String... keys) { + this.delegate = delegate; + this.keys = keys; + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { + if (column > keys.length) { + throw new IndexOutOfBoundsException("colum can not be greater than " + keys.length); + } + TableColumn col = table.getColumn(table.getColumnName(column)); + value = _(keys[col.getModelIndex()]); + return delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); + + /*JLabel rendererComponent = (JLabel) delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); + + rendererComponent.setText(_(keys[column])); + return rendererComponent;*/ + } +} Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java 2008-12-23 10:31:56 UTC (rev 1090) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -7,7 +7,11 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.ImageIcon; import javax.swing.JComboBox; +import javax.swing.JTable; import javax.swing.SwingUtilities; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; import javax.swing.text.AbstractDocument; import javax.swing.text.JTextComponent; import java.lang.reflect.Field; @@ -104,4 +108,22 @@ model.setSelectedItem(select); } + public static void fixTableColumnWidth(JTable table, int columnIndex, int width) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setMaxWidth(width); + column.setMinWidth(width); + column.setWidth(width); + column.setPreferredWidth(width); + } + + public static void setTableColumnEditor(JTable table, int columnIndex, TableCellEditor editor) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setCellEditor(editor); + } + + public static void setTableColumnRenderer(JTable table, int columnIndex, TableCellRenderer editor) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setCellRenderer(editor); + } + } Modified: lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java 2008-12-23 10:31:56 UTC (rev 1090) +++ lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -1,9 +1,15 @@ package jaxx.runtime; +import jaxx.runtime.JXPathDecorator.Context; import org.junit.After; import static org.junit.Assert.assertEquals; import org.junit.Test; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + /** @author chemit */ public class JXPathDecoratorTest { @@ -76,6 +82,67 @@ assertDecoratorInternal(); } + public static class Data { + int pos; + String name; + + protected static List<Data> generate(int nb) { + List<Data> datas = new ArrayList<Data>(nb); + for (int i = 0; i < nb; i++) { + datas.add(new Data(i, "name_" + (nb - i))); + } + return datas; + } + + Data(int pos, String name) { + this.pos = pos; + this.name = name; + } + + public int getPos() { + return pos; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "Data{pos=" + pos + ", name='" + name + '\'' + '}'; + } + } + + @Test + public void testSort() throws Exception { + + List<Data> datas = Data.generate(10); + JXPathDecorator<Data> decorator = JXPathDecorator.newDecorator(Data.class, "${pos}$d ${name}$s"); + + List<Data> sortData = new ArrayList<Data>(datas); + JXPathDecorator.sort(decorator, sortData, 0); + for (int i = 0; i < datas.size(); i++) { + Data data = datas.get(i); + Data sData = sortData.get(i); + assertEquals(data, sData); + } + Collections.sort(datas, new Comparator<Data>() { + @Override + public int compare(Data o1, Data o2) { + return o1.name.compareTo(o2.name); + } + }); + Context<Data> context = decorator.context; + context.setComparator(null); + JXPathDecorator.sort(decorator, sortData, 1); + for (int i = 0; i < datas.size(); i++) { + Data data = datas.get(i); + Data sData = sortData.get(i); + assertEquals(data, sData); + } + } + + public void assertDecoratorInternal(String... tokens) { assertTokens(tokens); expected = String.format(decorator.getExpression(), decorator.getExpression(), decorator.getNbToken()); Modified: lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java 2008-12-23 10:31:56 UTC (rev 1090) +++ lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java 2008-12-23 10:35:41 UTC (rev 1091) @@ -1,9 +1,15 @@ package jaxx.runtime; +import jaxx.runtime.JXPathDecoratorTest.Data; import org.junit.After; import static org.junit.Assert.assertEquals; import org.junit.Test; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + /** @author chemit */ public class MultiJXPathDecoratorTest { @@ -128,6 +134,35 @@ assertEquals(expected, result); } + @Test + public void testSort() throws Exception { + + List<Data> datas = Data.generate(10); + + MultiJXPathDecorator<Data> decorator = MultiJXPathDecorator.newDecorator(Data.class, "${pos}$d-${name}$s", "-"); + + List<Data> sortData = new ArrayList<Data>(datas); + JXPathDecorator.sort(decorator, sortData, 0); + for (int i = 0; i < datas.size(); i++) { + Data data = datas.get(i); + Data sData = sortData.get(i); + assertEquals(data, sData); + } + Collections.sort(datas, new Comparator<Data>() { + @Override + public int compare(Data o1, Data o2) { + return o1.name.compareTo(o2.name); + } + }); + decorator.setContextIndex(1); + JXPathDecorator.sort(decorator, sortData, 1); + for (int i = 0; i < datas.size(); i++) { + Data data = datas.get(i); + Data sData = sortData.get(i); + assertEquals(data, sData); + } + } + public void assertDecoratorInternal(String... tokens) { assertTokens(tokens); expected = String.format(decorator.getExpression(), decorator.getExpression(), decorator.getNbToken());
participants (1)
-
tchemit@users.labs.libre-entreprise.org