Author: nbelaevski
Date: 2010-12-02 09:47:41 -0500 (Thu, 02 Dec 2010)
New Revision: 20310
Added:
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNode.java
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNodeImpl.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeyConverter.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeySequenceRowKeyConverter.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/IntegerSequenceRowKeyConverter.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/ObjectSequenceRowKeyConverter.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/TreeConverterUtil.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeDataModelImpl.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeTuplesIterator.java
trunk/ui/iteration/ui/src/test/java/org/richfaces/convert/
trunk/ui/iteration/ui/src/test/java/org/richfaces/convert/TreeConverterUtilTest.java
Modified:
trunk/ui/iteration/api/src/main/java/org/richfaces/model/SwingTreeNodeImpl.java
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModel.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/SequenceRowKeyConverter.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelCompositeTuplesIterator.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelTuplesIterator.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeDataModelImpl.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeTuplesIterator.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeSequenceKeyModel.java
Log:
https://jira.jboss.org/browse/RF-9718
https://jira.jboss.org/browse/RF-9729
https://jira.jboss.org/browse/RF-9902
Modified: trunk/ui/iteration/api/src/main/java/org/richfaces/model/SwingTreeNodeImpl.java
===================================================================
---
trunk/ui/iteration/api/src/main/java/org/richfaces/model/SwingTreeNodeImpl.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/api/src/main/java/org/richfaces/model/SwingTreeNodeImpl.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -43,29 +43,29 @@
private static final long serialVersionUID = 8841984268370598781L;
private TreeNode parent;
-
+
private T data;
-
+
private Collection<TreeNode> children;
-
+
private boolean allowUpdateParents = true;
-
+
public SwingTreeNodeImpl() {
this(null);
}
-
- void setAllowUpdateParents(boolean allowUpdateParents) {
- this.allowUpdateParents = allowUpdateParents;
- }
-
+
public SwingTreeNodeImpl(Collection<TreeNode> children) {
this.children = wrapNull(children);
}
+ void setAllowUpdateParents(boolean allowUpdateParents) {
+ this.allowUpdateParents = allowUpdateParents;
+ }
+
private static Collection<TreeNode> wrapNull(Collection<TreeNode> src) {
return src != null ? src : Lists.<TreeNode>newArrayList();
}
-
+
public TreeNode getChildAt(int childIndex) {
return Iterables.get(children, childIndex);
}
@@ -81,7 +81,7 @@
public void setParent(TreeNode parent) {
this.parent = parent;
}
-
+
public int getIndex(TreeNode node) {
return Iterables.indexOf(children, Predicates.equalTo(node));
}
@@ -93,16 +93,16 @@
treeNodeImpl.setParent(this);
}
}
-
+
public void removeChild(TreeNode node) {
if (children.remove(node)) {
if (allowUpdateParents && node instanceof SwingTreeNodeImpl<?>)
{
SwingTreeNodeImpl<?> treeNodeImpl = (SwingTreeNodeImpl<?>)
node;
treeNodeImpl.setParent(null);
}
- }
+ }
}
-
+
public boolean getAllowsChildren() {
return true;
}
@@ -118,20 +118,20 @@
public T getData() {
return data;
}
-
+
public void setData(T data) {
this.data = data;
}
-
+
public Collection<TreeNode> getChildrenList() {
return children;
}
-
+
@Override
public String toString() {
ToStringHelper toStringHelper = Objects.toStringHelper(this);
toStringHelper.add("data", data);
-
+
return toStringHelper.toString();
}
}
Modified: trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModel.java
===================================================================
--- trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModel.java 2010-12-02
14:32:03 UTC (rev 20309)
+++ trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModel.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -23,7 +23,9 @@
import java.util.Iterator;
+import javax.faces.convert.Converter;
+
/**
* @author Nick Belaevski
*
@@ -31,6 +33,8 @@
//TODO - add necessary methods for tree adaptors support
public interface TreeDataModel<E> {
+ public static final char SEPARATOR_CHAR = '.';
+
public Object getRowKey();
public void setRowKey(Object rowKey);
@@ -53,4 +57,6 @@
public void restoreFromSnapshot(TreeDataModelTuple tuple);
+ public Converter getRowKeyConverter();
+
}
Added: trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNode.java
===================================================================
--- trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNode.java
(rev 0)
+++ trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNode.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.model;
+
+import java.util.Iterator;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface TreeNode {
+
+ public TreeNode getChild(Object key);
+
+ public int indexOf(Object key);
+
+ public Iterator<Object> getChildrenKeysIterator();
+
+ public boolean isLeaf();
+
+ public void addChild(Object key, TreeNode child);
+
+ public void insertChild(int idx, Object key, TreeNode child);
+
+ public void removeChild(Object key);
+
+}
Added: trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNodeImpl.java
===================================================================
--- trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNodeImpl.java
(rev 0)
+++ trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeNodeImpl.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.model;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class TreeNodeImpl implements TreeNode {
+
+ private List<Object> keysList = null;
+
+ private Map<Object, TreeNode> children = null;
+
+ private boolean leaf;
+
+ public TreeNodeImpl() {
+ this(false);
+ }
+
+ public TreeNodeImpl(boolean leaf) {
+ super();
+
+ this.leaf = leaf;
+
+ if (!leaf) {
+ keysList = Lists.newArrayList();
+ children = Maps.newHashMap();
+ }
+ }
+
+ public void addChild(Object key, TreeNode child) {
+ if (isLeaf()) {
+ throw new IllegalStateException("Cannot add children to leaf");
+ }
+
+ keysList.add(key);
+ children.put(key, child);
+ }
+
+ public void insertChild(int idx, Object key, TreeNode child) {
+ if (isLeaf()) {
+ throw new IllegalStateException("Cannot add children to leaf");
+ }
+
+ keysList.add(idx, key);
+ children.put(key, child);
+ }
+
+ public void removeChild(Object key) {
+ if (isLeaf()) {
+ return;
+ }
+
+ children.remove(key);
+ keysList.remove(key);
+ }
+
+ public TreeNode getChild(Object key) {
+ if (isLeaf()) {
+ return null;
+ }
+
+ return children.get(key);
+ }
+
+ public Iterator<Object> getChildrenKeysIterator() {
+ if (isLeaf()) {
+ return Iterators.emptyIterator();
+ }
+
+ return Iterators.unmodifiableIterator(keysList.iterator());
+ }
+
+ public int indexOf(Object key) {
+ if (isLeaf()) {
+ return -1;
+ }
+
+ return keysList.indexOf(key);
+ }
+
+ public boolean isLeaf() {
+ return leaf;
+ }
+
+}
Modified: trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -61,7 +61,6 @@
import org.richfaces.component.util.MessageUtil;
import org.richfaces.context.ExtendedVisitContext;
import org.richfaces.context.ExtendedVisitContextMode;
-import org.richfaces.convert.SequenceRowKeyConverter;
import org.richfaces.event.TreeSelectionChangeEvent;
import org.richfaces.event.TreeSelectionChangeListener;
import org.richfaces.event.TreeSelectionChangeSource;
@@ -126,8 +125,6 @@
}
};
- private static final Converter ROW_KEY_CONVERTER = new SequenceRowKeyConverter();
-
private enum PropertyKeys {
selection
}
@@ -231,7 +228,7 @@
public Converter getRowKeyConverter() {
Converter converter = super.getRowKeyConverter();
if (converter == null) {
- converter = ROW_KEY_CONVERTER;
+ converter = getTreeDataModel().getRowKeyConverter();
}
return converter;
}
@@ -255,6 +252,10 @@
}
public AbstractTreeNode findTreeNodeComponent() {
+ if (getRowKey() == null) {
+ return null;
+ }
+
FacesContext facesContext = getFacesContext();
String nodeType = getNodeType();
@@ -319,7 +320,7 @@
boolean newExpandedValue = toggleEvent.isExpanded();
FacesContext context = getFacesContext();
- ValueExpression expression =
getValueExpression(AbstractTreeNode.PropertyKeys.expanded.toString());
+ ValueExpression expression =
treeNodeComponent.getValueExpression(AbstractTreeNode.PropertyKeys.expanded.toString());
if (expression != null) {
ELContext elContext = context.getELContext();
Exception caught = null;
@@ -465,10 +466,6 @@
@Attribute(hidden = true)
public boolean isLeaf() {
- if (getRowKey() == null) {
- return false;
- }
-
return getTreeDataModel().isLeaf();
}
Modified: trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java 2010-12-02
14:32:03 UTC (rev 20309)
+++ trunk/ui/iteration/ui/src/main/java/org/richfaces/component/TreeRange.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -41,10 +41,18 @@
}
public boolean shouldProcessNode() {
+ if (tree.getRowKey() == null) {
+ return true;
+ }
+
return tree.findTreeNodeComponent() != null;
}
public boolean shouldIterateChildren() {
+ if (tree.getRowKey() == null) {
+ return true;
+ }
+
if (tree.isLeaf()) {
return false;
}
Added:
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeyConverter.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeyConverter.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeyConverter.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,102 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import static org.richfaces.convert.TreeConverterUtil.escape;
+import static org.richfaces.convert.TreeConverterUtil.unescape;
+
+import java.util.Iterator;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+
+import org.richfaces.model.DeclarativeModelKey;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class DeclarativeModelKeyConverter implements Converter {
+
+ private static final class StaticHolder {
+
+ static final Joiner JOINER;
+
+ static final Splitter SPLITTER;
+
+ static {
+ char separatorChar =
UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance());
+ JOINER = Joiner.on(separatorChar);
+ SPLITTER = Splitter.on(separatorChar);
+ }
+
+ private StaticHolder() {}
+
+ }
+
+ private Converter delegateConverter;
+
+ public DeclarativeModelKeyConverter(Converter delegateConverter) {
+ super();
+ this.delegateConverter = delegateConverter;
+ }
+
+ public Object getAsObject(FacesContext context, UIComponent component, String value)
{
+ if (Strings.isNullOrEmpty(value)) {
+ return null;
+ }
+
+ String s = unescape(value);
+
+ Iterator<String> split = StaticHolder.SPLITTER.split(s).iterator();
+
+ String modelId = (String) split.next();
+ Object modelKey = delegateConverter.getAsObject(context, component,
split.next());
+
+ if (split.hasNext()) {
+ throw new ConverterException(value);
+ }
+
+ return new DeclarativeModelKey(modelId, modelKey);
+ }
+
+ public String getAsString(FacesContext context, UIComponent component, Object value)
{
+ if (value == null) {
+ return "";
+ }
+
+ DeclarativeModelKey declarativeModelKey = (DeclarativeModelKey) value;
+
+ String convertedModelKey = delegateConverter.getAsString(context, component,
declarativeModelKey.getModelKey());
+ String keyString = StaticHolder.JOINER.join(declarativeModelKey.getModelId(),
convertedModelKey);
+
+ return escape(keyString);
+ }
+
+}
Added:
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeySequenceRowKeyConverter.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeySequenceRowKeyConverter.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/DeclarativeModelKeySequenceRowKeyConverter.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import javax.faces.convert.IntegerConverter;
+
+import org.richfaces.model.DeclarativeModelKey;
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class DeclarativeModelKeySequenceRowKeyConverter extends
SequenceRowKeyConverter<DeclarativeModelKey> {
+
+ public DeclarativeModelKeySequenceRowKeyConverter() {
+ super(DeclarativeModelKey.class, new DeclarativeModelKeyConverter(new
IntegerConverter()));
+ }
+
+
+}
Added:
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/IntegerSequenceRowKeyConverter.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/IntegerSequenceRowKeyConverter.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/IntegerSequenceRowKeyConverter.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,36 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import javax.faces.convert.IntegerConverter;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class IntegerSequenceRowKeyConverter extends
SequenceRowKeyConverter<Integer> {
+
+ public IntegerSequenceRowKeyConverter() {
+ super(Integer.class, new IntegerConverter());
+ }
+
+}
Added:
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/ObjectSequenceRowKeyConverter.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/ObjectSequenceRowKeyConverter.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/ObjectSequenceRowKeyConverter.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class ObjectSequenceRowKeyConverter extends SequenceRowKeyConverter<Object>
{
+
+ private static final Converter NO_OP_CONVERTER = new Converter() {
+
+ public String getAsString(FacesContext context, UIComponent component, Object
value) {
+ return (String) value;
+ }
+
+ public Object getAsObject(FacesContext context, UIComponent component, String
value) {
+ return value;
+ }
+ };
+
+ public ObjectSequenceRowKeyConverter() {
+ super(Object.class, NO_OP_CONVERTER);
+ }
+
+}
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/SequenceRowKeyConverter.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/SequenceRowKeyConverter.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/SequenceRowKeyConverter.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -1,63 +1,52 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
package org.richfaces.convert;
+import java.util.List;
+
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
-
+import javax.faces.convert.ConverterException;
+import static org.richfaces.model.TreeDataModel.*;
import org.richfaces.model.SequenceRowKey;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
-import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.ObjectArrays;
/**
* @author Nick Belaevski
- *
+ * @since 3.3.1
*/
-public class SequenceRowKeyConverter implements Converter {
- private static final Joiner DOT_JOINER = Joiner.on('.');
+public class SequenceRowKeyConverter<T> implements Converter {
- private static final Splitter DOT_SPLITTER = Splitter.on('.');
+ private static final Splitter DOT_SPLITTER = Splitter.on(SEPARATOR_CHAR);
- private static final Function<String, Integer> INTEGER_PARSER = new
Function<String, Integer>() {
- public Integer apply(String from) {
- return Integer.parseInt(from);
- };
- };
+ private Class<T> clazz;
- public Object getAsObject(FacesContext context, UIComponent component, String value)
{
+ private Converter delegateConverter;
+
+ public SequenceRowKeyConverter(Class<T> clazz, Converter delegateConverter) {
+ super();
+ this.clazz = clazz;
+ this.delegateConverter = delegateConverter;
+ }
+
+ public Object getAsObject(FacesContext context, UIComponent component, String value)
throws ConverterException {
if (Strings.isNullOrEmpty(value)) {
return null;
}
Iterable<String> split = DOT_SPLITTER.split(value);
-
- //TODO - handle another types
- return new
SequenceRowKey<Integer>(Iterables.toArray(Iterables.transform(split,
INTEGER_PARSER), Integer.class));
+ List<T> keysList = Lists.<T>newArrayList();
+
+ for (String s: split) {
+ T convertedKey = clazz.cast(delegateConverter.getAsObject(context, component,
s));
+ keysList.add(convertedKey);
+ }
+
+ return new SequenceRowKey(keysList.toArray(ObjectArrays.newArray(clazz,
keysList.size())));
}
public String getAsString(FacesContext context, UIComponent component, Object value)
{
@@ -65,10 +54,20 @@
return "";
}
- SequenceRowKey<?> sequenceRowKey = (SequenceRowKey<?>) value;
- Object[] simpleKeys=sequenceRowKey.getSimpleKeys();
-
- return DOT_JOINER.join(simpleKeys);
+ SequenceRowKey sequenceRowKey = (SequenceRowKey) value;
+
+ StringBuilder result = new StringBuilder();
+
+ for (Object simpleKey: sequenceRowKey.getSimpleKeys()) {
+ String convertedKey = delegateConverter.getAsString(context, component,
simpleKey);
+
+ if (result.length() > 0) {
+ result.append(SEPARATOR_CHAR);
+ }
+
+ result.append(convertedKey);
+ }
+
+ return result.toString();
}
-
}
Added: trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/TreeConverterUtil.java
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/TreeConverterUtil.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/convert/TreeConverterUtil.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,264 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import java.text.MessageFormat;
+
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public final class TreeConverterUtil {
+
+ private static final class SeparatorCharHolder {
+
+ static final char SEPARATOR_CHAR =
UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance());
+
+ private SeparatorCharHolder() {}
+
+ }
+
+ private static final char ESCAPE_CHAR = '_';
+
+ private TreeConverterUtil() {}
+
+ private static boolean shouldEscape(char c) {
+ if ('a' <= c && c <= 'z') {
+ return false;
+ }
+
+ if ('A' <= c && c <= 'Z') {
+ return false;
+ }
+
+ if ('0' <= c && c <= '9') {
+ return false;
+ }
+
+ if (c == ESCAPE_CHAR || c == SeparatorCharHolder.SEPARATOR_CHAR) {
+ return true;
+ }
+
+ if ('-' == c || '\u00B7' == c) {
+ return false;
+ }
+
+ if ('\u00C0' <= c && c <= '\u00D6') {
+ return false;
+ }
+
+ if ('\u00D8' <= c && c <= '\u00F6') {
+ return false;
+ }
+
+ if ('\u00F8' <= c && c <= '\u02FF') {
+ return false;
+ }
+
+ if ('\u0370' <= c && c <= '\u037D') {
+ return false;
+ }
+
+ if ('\u037F' <= c && c <= '\u1FFF') {
+ return false;
+ }
+
+ if ('\u200C' <= c && c <= '\u200D') {
+ return false;
+ }
+
+ if ('\u2070' <= c && c <= '\u218F') {
+ return false;
+ }
+
+ if ('\u2C00' <= c && c <= '\u2FEF') {
+ return false;
+ }
+
+ if ('\u3001' <= c && c <= '\uD7FF') {
+ return false;
+ }
+
+ if ('\uF900' <= c && c <= '\uFDCF') {
+ return false;
+ }
+
+ if ('\uFDF0' <= c && c <= '\uFFFD') {
+ return false;
+ }
+
+ if ('\u0300' <= c && c <= '\u036F') {
+ return false;
+ }
+
+ if ('\u203F' <= c && c <= '\u2040') {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static int parseHexString(String s) {
+ int result = 0;
+
+ for (int i = 0; i < s.length(); i++) {
+ result <<= 4;
+
+ char c = s.charAt(i);
+
+ int digitValue = Character.digit(c, 16);
+ if (digitValue < 0) {
+ throw new NumberFormatException();
+ }
+
+ result += digitValue;
+ }
+
+ return result;
+ }
+
+ private static void checkAvailable(String s, int idx, int len) {
+ if (s.length() < idx + len) {
+ throw new IllegalArgumentException(MessageFormat.format("Expected {0}
available chars in ''{1}'' string starting from {2} index", len, s,
idx));
+ }
+ }
+
+ private static char getNextChar(String s, int idx) {
+ checkAvailable(s, idx, 1);
+
+ return s.charAt(idx);
+ }
+
+ private static char readNextCharFromHexCode(String s, int idx, int len) {
+ checkAvailable(s, idx, len);
+
+ String numString = s.substring(idx, idx + len);
+ try {
+ int charValue = parseHexString(numString);
+ return (char) charValue;
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(MessageFormat.format("Substring
''{0}'' of ''{1}'' string is not a valid hex number
", numString, s));
+ }
+ }
+
+ public static String unescape(String s) {
+ StringBuilder sb = new StringBuilder(s.length());
+
+ int startIdx = 0;
+
+ while (startIdx >= 0) {
+ int idx = s.indexOf(ESCAPE_CHAR, startIdx);
+
+ if (idx >= 0) {
+ sb.append(s.subSequence(startIdx, idx));
+
+ idx++; //skip escape char
+
+ char c = getNextChar(s, idx);
+
+ switch (c) {
+ case ESCAPE_CHAR:
+ idx++;
+ sb.append(c);
+ break;
+
+ case 'x':
+ idx++;
+ sb.append(readNextCharFromHexCode(s, idx, 2));
+ idx += 2;
+ break;
+
+ case 'u':
+ idx++;
+ sb.append(readNextCharFromHexCode(s, idx, 4));
+ idx += 4;
+ break;
+
+ default:
+ throw new
IllegalArgumentException(MessageFormat.format("Unexpected char
''{0}'' in ''{1}'' string located at index {2}", c,
s, idx));
+ }
+
+
+ } else {
+ sb.append(s.subSequence(startIdx, s.length()));
+ }
+
+ startIdx = idx;
+ }
+
+ return sb.toString();
+ }
+
+
+ public static String escape(String s) {
+ StringBuilder sb = new StringBuilder(s.length());
+
+ int start = 0;
+
+ char[] cs = s.toCharArray();
+ for (int idx = 0; idx < cs.length; idx++) {
+ char c = cs[idx];
+
+ if (shouldEscape(c)) {
+ sb.append(cs, start, idx - start);
+ sb.append(ESCAPE_CHAR);
+
+ if (c == ESCAPE_CHAR) {
+ sb.append(c); // ${escapeChar}
+ } else {
+ String asHex = Integer.toHexString(c);
+ switch (asHex.length()) {
+
+ case 1:
+ sb.append("x0"); // _x05
+ break;
+ case 2:
+ sb.append("x"); // _xef
+ break;
+ case 3:
+ sb.append("u0"); // _u0fed
+ break;
+ case 4:
+ sb.append("u"); // _ufcda
+ break;
+
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ sb.append(asHex);
+ }
+
+ start = idx + 1;
+ }
+ }
+
+ if (start < s.length()) {
+ sb.append(cs, start, s.length() - start);
+ }
+
+ return sb.toString();
+ }
+}
Added:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeDataModelImpl.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeDataModelImpl.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeDataModelImpl.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.model;
+
+import java.util.Iterator;
+
+import javax.faces.convert.Converter;
+
+import org.richfaces.convert.ObjectSequenceRowKeyConverter;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class ClassicTreeNodeDataModelImpl extends TreeSequenceKeyModel<TreeNode> {
+
+ private static final Converter DEFAULT_CONVERTER = new
ObjectSequenceRowKeyConverter();
+
+ private TreeNode rootNode;
+
+ public boolean isLeaf() {
+ return getData().isLeaf();
+ }
+
+ public Iterator<TreeDataModelTuple> children() {
+ return new ClassicTreeNodeTuplesIterator(getData(), getRowKey());
+ }
+
+ @Override
+ protected TreeNode setupChildContext(Object segment) {
+ return getData().getChild(segment);
+ }
+
+ @Override
+ public Object getWrappedData() {
+ return rootNode;
+ }
+
+ @Override
+ public void setWrappedData(Object data) {
+ this.rootNode = (TreeNode) data;
+ }
+
+ public Converter getRowKeyConverter() {
+ return DEFAULT_CONVERTER;
+ }
+}
Added:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeTuplesIterator.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeTuplesIterator.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/ClassicTreeNodeTuplesIterator.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.model;
+
+import java.util.Iterator;
+
+import com.google.common.collect.UnmodifiableIterator;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+final class ClassicTreeNodeTuplesIterator extends
UnmodifiableIterator<TreeDataModelTuple> {
+
+ private TreeNode treeNode;
+
+ private SequenceRowKey baseKey;
+
+ private Iterator<Object> childrenKeysIterator = null;
+
+ public ClassicTreeNodeTuplesIterator(TreeNode treeNode, SequenceRowKey baseKey) {
+ super();
+ this.treeNode = treeNode;
+ this.baseKey = baseKey;
+ this.childrenKeysIterator = treeNode.getChildrenKeysIterator();
+ }
+
+ public boolean hasNext() {
+ return childrenKeysIterator.hasNext();
+ }
+
+ public TreeDataModelTuple next() {
+ Object nextChildKey = childrenKeysIterator.next();
+ Object rowKey = (baseKey != null ? baseKey.append(nextChildKey) : new
SequenceRowKey(nextChildKey));
+
+ return new TreeDataModelTuple(rowKey, treeNode.getChild(nextChildKey));
+ }
+
+}
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -23,6 +23,8 @@
import java.io.Serializable;
+import com.google.common.base.Objects;
+
/**
* @author Nick Belaevski
*
@@ -89,6 +91,6 @@
@Override
public String toString() {
- return getModelId() + "." + getModelKey();
+ return Objects.toStringHelper(this).add("modelId",
getModelId()).add("modelKey", getModelKey()).toString();
}
}
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelCompositeTuplesIterator.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelCompositeTuplesIterator.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelCompositeTuplesIterator.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -40,11 +40,11 @@
private UIComponent component;
- private SequenceRowKey<DeclarativeModelKey> key;
+ private SequenceRowKey key;
private Iterator<TreeDataModelTuple> iterator;
- public DeclarativeTreeDataModelCompositeTuplesIterator(UIComponent component,
SequenceRowKey<DeclarativeModelKey> key) {
+ public DeclarativeTreeDataModelCompositeTuplesIterator(UIComponent component,
SequenceRowKey key) {
super();
this.component = component;
this.key = key;
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -21,17 +21,17 @@
*/
package org.richfaces.model;
-import static com.google.common.base.Objects.firstNonNull;
-
import java.util.Iterator;
import java.util.Map;
import javax.faces.component.UIComponent;
+import javax.faces.convert.Converter;
import org.richfaces.component.AbstractTree;
import org.richfaces.component.ComponentPredicates;
import org.richfaces.component.TreeModelAdaptor;
import org.richfaces.component.TreeModelRecursiveAdaptor;
+import org.richfaces.convert.DeclarativeModelKeySequenceRowKeyConverter;
import org.richfaces.log.Logger;
import org.richfaces.log.RichfacesLogger;
@@ -42,11 +42,11 @@
* @author Nick Belaevski
*
*/
-public class DeclarativeTreeDataModelImpl extends
TreeSequenceKeyModel<DeclarativeModelKey, Object> implements
DeclarativeTreeModel<Object> {
+public class DeclarativeTreeDataModelImpl extends TreeSequenceKeyModel<Object>
implements DeclarativeTreeModel<Object> {
private static final Logger LOGGER = RichfacesLogger.MODEL.getLogger();
- private static final SequenceRowKey<DeclarativeModelKey> EMPTY_KEY = new
SequenceRowKey<DeclarativeModelKey>();
+ private static final Converter DEFAULT_CONVERTER = new
DeclarativeModelKeySequenceRowKeyConverter();
private String var;
@@ -57,7 +57,6 @@
private UIComponent currentComponent;
public DeclarativeTreeDataModelImpl(AbstractTree tree, String var, Map<String,
Object> contextMap) {
- super();
this.tree = tree;
this.currentComponent = tree;
this.var = var;
@@ -82,13 +81,9 @@
}
public Iterator<TreeDataModelTuple> children() {
- return new DeclarativeTreeDataModelCompositeTuplesIterator(currentComponent,
safeGetRowKey());
+ return new DeclarativeTreeDataModelCompositeTuplesIterator(currentComponent,
getRowKey());
}
- public Object getParentRowKey(Object rowKey) {
- return safeGetRowKey().getParent();
- }
-
@Override
public Object getWrappedData() {
throw new UnsupportedOperationException();
@@ -100,7 +95,7 @@
}
@Override
- protected void walkKey(SequenceRowKey<DeclarativeModelKey> key) {
+ protected void setupKey(SequenceRowKey key) {
Object initialContextValue = null;
if (var != null) {
@@ -110,7 +105,7 @@
try {
this.currentComponent = tree;
- super.walkKey(key);
+ super.setupKey(key);
} finally {
if (var != null) {
try {
@@ -121,24 +116,29 @@
}
}
}
-
+
@Override
- protected void walkNext(DeclarativeModelKey segment) {
+ protected Object setupChildContext(Object keyObject) {
+ DeclarativeModelKey segment = (DeclarativeModelKey) keyObject;
+ if (var != null) {
+ contextMap.put(var, getData());
+ }
+
String modelId = segment.getModelId();
-
+
UIComponent modelComponent;
-
+
if (currentComponent instanceof TreeModelRecursiveAdaptor &&
modelId.equals(currentComponent.getId())) {
modelComponent = currentComponent;
} else {
modelComponent = Iterables.find(currentComponent.getChildren(),
ComponentPredicates.withId(modelId));
}
-
+
Object nodes = null;
-
+
if (modelComponent instanceof TreeModelRecursiveAdaptor) {
TreeModelRecursiveAdaptor recursiveAdaptor = (TreeModelRecursiveAdaptor)
modelComponent;
-
+
if (currentComponent.equals(modelComponent)) {
nodes = recursiveAdaptor.getNodes();
} else {
@@ -147,20 +147,13 @@
} else {
nodes = ((TreeModelAdaptor) modelComponent).getNodes();
}
-
+
Object data = Iterables.get((Iterable<?>) nodes, (Integer)
segment.getModelKey());
- setRowKeyAndData(safeGetRowKey().append(segment), data);
this.currentComponent = modelComponent;
-
- if (var != null) {
- contextMap.put(var, data);
- }
+
+ return data;
}
-
- private SequenceRowKey<DeclarativeModelKey> safeGetRowKey() {
- return firstNonNull(getRowKey(), EMPTY_KEY);
- }
-
+
public TreeDataModelTuple createSnapshot() {
return new DeclarativeTreeDataModelTuple(getRowKey(), getData(),
getCurrentComponent());
}
@@ -172,4 +165,7 @@
this.currentComponent = declarativeModelTuple.getComponent();
}
+ public Converter getRowKeyConverter() {
+ return DEFAULT_CONVERTER;
+ }
}
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelTuplesIterator.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelTuplesIterator.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelTuplesIterator.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -25,17 +25,19 @@
import javax.faces.component.UIComponent;
-final class DeclarativeTreeDataModelTuplesIterator implements
Iterator<TreeDataModelTuple> {
+import com.google.common.collect.UnmodifiableIterator;
+
+final class DeclarativeTreeDataModelTuplesIterator extends
UnmodifiableIterator<TreeDataModelTuple> {
private UIComponent component;
- private SequenceRowKey<DeclarativeModelKey> baseKey;
+ private SequenceRowKey baseKey;
private int counter = 0;
private Iterator<?> dataIterator;
- public DeclarativeTreeDataModelTuplesIterator(UIComponent component,
SequenceRowKey<DeclarativeModelKey> baseKey, Iterator<?> dataIterator) {
+ public DeclarativeTreeDataModelTuplesIterator(UIComponent component, SequenceRowKey
baseKey, Iterator<?> dataIterator) {
super();
this.component = component;
this.baseKey = baseKey;
@@ -46,7 +48,7 @@
Object nextNode = dataIterator.next();
DeclarativeModelKey key = new DeclarativeModelKey(component.getId(), counter++);
- SequenceRowKey<DeclarativeModelKey> newKey = baseKey.append(key);
+ SequenceRowKey newKey = (baseKey != null ? baseKey.append(key) : new
SequenceRowKey(key));
return new DeclarativeTreeDataModelTuple(newKey, nextNode, component);
}
@@ -55,8 +57,4 @@
return dataIterator.hasNext();
}
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
}
\ No newline at end of file
Modified: trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java 2010-12-02
14:32:03 UTC (rev 20309)
+++ trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SequenceRowKey.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -30,41 +30,33 @@
* @author Nick Belaevski
*
*/
-public class SequenceRowKey<T> implements Serializable {
+public class SequenceRowKey implements Serializable {
private static final long serialVersionUID = 5605581090240141910L;
- private T[] simpleKeys;
+ private Object[] simpleKeys;
- public SequenceRowKey(T... keys) {
+ public SequenceRowKey(Object... keys) {
super();
this.simpleKeys = keys;
}
- public T[] getSimpleKeys() {
+ public Object[] getSimpleKeys() {
return simpleKeys;
}
- public SequenceRowKey<T> append(T segment) {
- return new SequenceRowKey<T>(ObjectArrays.concat(simpleKeys, segment));
+ public SequenceRowKey append(Object segment) {
+ return new SequenceRowKey(ObjectArrays.concat(simpleKeys, segment));
}
- public T getLastKeySegment() {
+ public SequenceRowKey getParent() {
if (simpleKeys.length == 0) {
return null;
}
- return simpleKeys[simpleKeys.length - 1];
- }
-
- public SequenceRowKey<T> getParent() {
- if (simpleKeys.length == 0) {
- return null;
- }
-
- T[] parentSimpleKeys = ObjectArrays.newArray(simpleKeys, simpleKeys.length - 1);
+ Object[] parentSimpleKeys = ObjectArrays.newArray(simpleKeys, simpleKeys.length -
1);
System.arraycopy(simpleKeys, 0, parentSimpleKeys, 0, parentSimpleKeys.length);
- return new SequenceRowKey<T>(parentSimpleKeys);
+ return new SequenceRowKey(parentSimpleKeys);
}
@Override
@@ -86,7 +78,7 @@
if (getClass() != obj.getClass()) {
return false;
}
- SequenceRowKey<?> other = (SequenceRowKey<?>) obj;
+ SequenceRowKey other = (SequenceRowKey) obj;
if (!Arrays.equals(simpleKeys, other.simpleKeys)) {
return false;
}
@@ -97,4 +89,5 @@
public String toString() {
return getClass().getName() + Arrays.toString(simpleKeys);
}
-}
+
+}
\ No newline at end of file
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeDataModelImpl.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeDataModelImpl.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeDataModelImpl.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -21,23 +21,24 @@
*/
package org.richfaces.model;
-import static com.google.common.base.Objects.firstNonNull;
-
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
+import javax.faces.convert.Converter;
import javax.swing.tree.TreeNode;
+import org.richfaces.convert.IntegerSequenceRowKeyConverter;
+
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
/**
* @author Nick Belaevski
*
*/
-public class SwingTreeNodeDataModelImpl extends TreeSequenceKeyModel<Integer,
TreeNode> {
+public class SwingTreeNodeDataModelImpl extends TreeSequenceKeyModel<TreeNode> {
- private static final SequenceRowKey<Integer> EMPTY_KEY = new
SequenceRowKey<Integer>();
+ private static final Converter DEFAULT_CONVERTER = new
IntegerSequenceRowKeyConverter();
private boolean asksAllowsChildren = false;
@@ -61,10 +62,6 @@
return treeNodeImpl;
}
- public Object getParentRowKey(Object rowKey) {
- throw new UnsupportedOperationException();
- }
-
public void setWrappedData(Object data) {
this.wrappedData = data;
@@ -93,14 +90,11 @@
}
@Override
- protected void walkNext(Integer segment) {
- TreeNode child = findChild(getData(), segment);
- //TODO what if node is missing?
- //TODO - optimize - remove partial keys creation
- setRowKeyAndData(safeGetRowKey().append(segment), child);
+ protected TreeNode setupChildContext(Object segment) {
+ return findChild(getData(), (Integer) segment);
}
-
- private SequenceRowKey<Integer> safeGetRowKey() {
- return firstNonNull(getRowKey(), EMPTY_KEY);
+
+ public Converter getRowKeyConverter() {
+ return DEFAULT_CONVERTER;
}
}
\ No newline at end of file
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeTuplesIterator.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeTuplesIterator.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/SwingTreeNodeTuplesIterator.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -25,15 +25,17 @@
import javax.swing.tree.TreeNode;
-final class SwingTreeNodeTuplesIterator implements Iterator<TreeDataModelTuple> {
+import com.google.common.collect.UnmodifiableIterator;
- private SequenceRowKey<Integer> baseKey;
+final class SwingTreeNodeTuplesIterator extends
UnmodifiableIterator<TreeDataModelTuple> {
+
+ private SequenceRowKey baseKey;
private Iterator<TreeNode> children;
private int counter = 0;
- SwingTreeNodeTuplesIterator(SequenceRowKey<Integer> baseKey,
Iterator<TreeNode> children) {
+ SwingTreeNodeTuplesIterator(SequenceRowKey baseKey, Iterator<TreeNode>
children) {
this.baseKey = baseKey;
this.children = children;
}
@@ -49,19 +51,15 @@
public TreeDataModelTuple next() {
TreeNode node = children.next();
- SequenceRowKey<Integer> key;
+ SequenceRowKey key;
if (baseKey != null) {
key = baseKey.append(getNextCounterValue());
} else {
- key = new SequenceRowKey<Integer>(getNextCounterValue());
+ key = new SequenceRowKey(getNextCounterValue());
}
return new TreeDataModelTuple(key, node);
}
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
}
\ No newline at end of file
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeSequenceKeyModel.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeSequenceKeyModel.java 2010-12-02
14:32:03 UTC (rev 20309)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/TreeSequenceKeyModel.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -32,29 +32,35 @@
* @author Nick Belaevski
*
*/
-public abstract class TreeSequenceKeyModel<K, V> extends ExtendedDataModel<V>
implements TreeDataModel<V> {
+public abstract class TreeSequenceKeyModel<V> extends ExtendedDataModel<V>
implements TreeDataModel<V> {
private V rootNode;
private V data;
- private SequenceRowKey<K> rowKey;
+ private SequenceRowKey rowKey;
- public SequenceRowKey<K> getRowKey() {
+ public SequenceRowKey getRowKey() {
return rowKey;
}
public void setRowKey(Object rowKey) {
+ SequenceRowKey sequenceKey = (SequenceRowKey) rowKey;
+
if (this.rowKey == null || !this.rowKey.equals(rowKey)) {
- walkKey((SequenceRowKey<K>) rowKey);
+ setupKey(sequenceKey);
}
}
-
+
protected void resetRowKeyAndData() {
setRowKeyAndData(null, rootNode);
}
- protected void setRowKeyAndData(SequenceRowKey<K> key, V data) {
+ protected void setData(V data) {
+ this.data = data;
+ }
+
+ protected void setRowKeyAndData(SequenceRowKey key, V data) {
this.rowKey = key;
this.data = data;
}
@@ -71,17 +77,22 @@
return data;
}
- protected void walkKey(SequenceRowKey<K> key) {
+ protected void setupKey(SequenceRowKey key) {
resetRowKeyAndData();
if (key != null) {
- for (K simpleKey: key.getSimpleKeys()) {
- walkNext(simpleKey);
+ V data = getRootNode();
+
+ for (Object simpleKey: key.getSimpleKeys()) {
+ data = setupChildContext(simpleKey);
+ setData(data);
}
+
+ setRowKeyAndData(key, data);
}
}
- protected abstract void walkNext(K segment);
+ protected abstract V setupChildContext(Object segment);
protected V getRootNode() {
return rootNode;
@@ -132,6 +143,16 @@
}
public void restoreFromSnapshot(TreeDataModelTuple tuple) {
- setRowKeyAndData((SequenceRowKey<K>) tuple.getRowKey(), (V)
tuple.getData());
+ setRowKeyAndData((SequenceRowKey) tuple.getRowKey(), (V) tuple.getData());
}
+
+ public Object getParentRowKey(Object rowKey) {
+ SequenceRowKey key = getRowKey();
+
+ if (key == null) {
+ return null;
+ }
+
+ return key.getParent();
+ }
}
Added:
trunk/ui/iteration/ui/src/test/java/org/richfaces/convert/TreeConverterUtilTest.java
===================================================================
--- trunk/ui/iteration/ui/src/test/java/org/richfaces/convert/TreeConverterUtilTest.java
(rev 0)
+++
trunk/ui/iteration/ui/src/test/java/org/richfaces/convert/TreeConverterUtilTest.java 2010-12-02
14:47:41 UTC (rev 20310)
@@ -0,0 +1,194 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.richfaces.convert.TreeConverterUtil.escape;
+import static org.richfaces.convert.TreeConverterUtil.unescape;
+
+import java.util.HashMap;
+
+import javax.faces.context.FacesContext;
+
+import org.jboss.test.faces.mock.Environment;
+import org.jboss.test.faces.mock.Mock;
+import org.jboss.test.faces.mock.MockFacesEnvironment;
+import org.jboss.test.faces.mock.MockTestRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+(a)RunWith(MockTestRunner.class)
+public class TreeConverterUtilTest {
+
+ @Mock
+ private FacesContext context;
+
+ @Mock
+ @Environment({Environment.Feature.EXTERNAL_CONTEXT})
+ private MockFacesEnvironment environment;
+
+ @Before
+ public void setUp() throws Exception {
+ environment.resetToNice();
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ expect(facesContext.getAttributes()).andStubReturn(new HashMap<Object,
Object>());
+ environment.replay();
+ }
+
+ @Test
+ public void testUnescape() throws Exception {
+ assertEquals("", unescape(""));
+ assertEquals("a", unescape("a"));
+ assertEquals("abc", unescape("abc"));
+
+
+ assertEquals("_", unescape("__"));
+ assertEquals("__", unescape("____"));
+
+ assertEquals("_a", unescape("__a"));
+ assertEquals("_abc", unescape("__abc"));
+
+ assertEquals("a_", unescape("a__"));
+ assertEquals("abc_", unescape("abc__"));
+
+ assertEquals("some_test", unescape("some__test"));
+
+ assertEquals("\u0000", unescape("_x00"));
+ assertEquals("\u0001", unescape("_x01"));
+ assertEquals("\u0010", unescape("_x10"));
+ assertEquals("\u0077", unescape("_x77"));
+ assertEquals("\u00A9", unescape("_xa9"));
+ assertEquals("\u00FF", unescape("_xFF"));
+ assertEquals("\u00FF", unescape("_xff"));
+
+ assertEquals(".", unescape("_x2e"));
+
+ assertEquals("\u0000", unescape("_u0000"));
+ assertEquals("\u0001", unescape("_u0001"));
+ assertEquals("\uE1A4", unescape("_ue1a4"));
+ assertEquals("\uF000", unescape("_uF000"));
+ assertEquals("\uFFFF", unescape("_uFFFF"));
+
+
+ assertEquals(".", unescape("_u002E"));
+
+ assertEquals("Embedded_underscores\u0312unicode\u0045etc",
unescape("Embedded__underscores_u0312unicode_x45etc"));
+
+ try {
+ unescape("_");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("some _a string");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("_x");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("_x0");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("_u");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("_u-1aaa");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("_u1zaa");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("embedded _x 00 into string");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("embedded _x0 into string");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+
+ try {
+ unescape("embedded _u012 into string");
+
+ fail();
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testEscape() throws Exception {
+ assertEquals("", escape(""));
+ assertEquals("__a__b__", escape("_a_b_"));
+ assertEquals("_x3a0_x3a1", escape(":0:1"));
+ assertEquals("testTEST05", escape("testTEST05"));
+ assertEquals("a_xa9c", escape("a\u00a9c"));
+ assertEquals("a_u037ec", escape("a\u037ec"));
+ assertEquals("a_ue1acd", escape("a\ue1acd"));
+ }
+}