Author: gvanmatre
Date: Tue Jun 27 21:04:20 2006
New Revision: 417663
URL: http://svn.apache.org/viewvc?rev=417663&view=rev
Log:
Fix for issue SHALE-201 reported by Ryan Wynn.
Modified:
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/CreateComponentCommand.java
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/SymbolsTestCase.java
Modified:
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java
URL:
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java?rev=417663&r1=417662&r2=417663&view=diff
==============================================================================
---
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java
(original)
+++
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/Clay.java
Tue Jun 27 21:04:20 2006
@@ -302,6 +302,8 @@
Map symbolTable = new TreeMap();
symbolTable.putAll(getSymbols());
clayContext.setSymbols(symbolTable);
+ //evaluate nested symbols
+ AbstractCommand.realizeSymbols(clayContext);
//resolve the literal "@managed-bean-name"
String expr = AbstractCommand.replaceMnemonic(clayContext,
getShapeValidator());
@@ -338,6 +340,9 @@
symbolTable.putAll(getDisplayElementRoot().getSymbols());
symbolTable.putAll(getSymbols());
clayContext.setSymbols(symbolTable);
+
+ //evaluate nested symbols
+ AbstractCommand.realizeSymbols(clayContext);
clayContext.setRootElement(getDisplayElementRoot());
clayContext.setParent(this);
Modified:
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java
URL:
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java?rev=417663&r1=417662&r2=417663&view=diff
==============================================================================
---
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java
(original)
+++
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AbstractCommand.java
Tue Jun 27 21:04:20 2006
@@ -19,8 +19,13 @@
package org.apache.shale.clay.component.chain;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.CatalogFactory;
@@ -87,6 +92,150 @@
public static String replaceMnemonic(ClayContext context) {
return replaceMnemonic(context, context.getAttribute().getValue());
}
+
+ /**
+ * <p>Evaluates nested symbols. These are symbols that have references to
other
+ * symbols as their values. The nested symbols evaluation is sensitive to
dependencies.
+ * The current scoped symbol table is found in the [EMAIL PROTECTED]
ClayContext}.</p>
+ */
+ public static void realizeSymbols(ClayContext context) {
+ Map symbols = context.getSymbols();
+ if (symbols == null || symbols.isEmpty())
+ return;
+
+ Iterator si = symbols.entrySet().iterator();
+
+ Map dependenciesMap = new TreeMap();
+ TreeSet allNestedSymbols = new TreeSet();
+
+ while (si.hasNext()) {
+ Map.Entry e = (Map.Entry) si.next();
+ SymbolBean symbol = (SymbolBean) e.getValue();
+ if (symbol.getValue() != null) {
+ List symbolDependencies = findSymbols(context,
symbol.getValue());
+ if (!symbolDependencies.isEmpty()) {
+ dependenciesMap.put(symbol.getName(), symbolDependencies);
+ allNestedSymbols.addAll(symbolDependencies);
+ allNestedSymbols.add(symbol.getName());
+ }
+ }
+ }
+
+ List allNestedSymbolsOrdered =
getOrderedByDependencies(allNestedSymbols, dependenciesMap);
+ for (int i = 0; i < allNestedSymbolsOrdered.size(); i++) {
+ String symbolName = (String) allNestedSymbolsOrdered.get(i);
+ SymbolBean sourceSymbol = (SymbolBean) symbols.get(symbolName);
+ if (sourceSymbol != null && sourceSymbol.getValue() != null) {
+ String value = replaceMnemonic(context,
sourceSymbol.getValue());
+ SymbolBean targetSymbol = new SymbolBean();
+ targetSymbol.setDescription(sourceSymbol.getDescription());
+ targetSymbol.setName(sourceSymbol.getName());
+ targetSymbol.setValue(value);
+
+ symbols.put(targetSymbol.getName(), targetSymbol);
+ }
+ }
+
+
+ }
+
+ /**
+ * <p>Orders the symbols by their dependencies. Each symbol
+ * can have multiple dependencies.</p>
+ *
+ * @param allNestedSymbols Set of symbol names
+ * @param dependenciesMap List of dependencies for each symbol
+ * @return ordered list of symbol names ordered by dependencies
+ */
+ private static List getOrderedByDependencies(Set allNestedSymbols, Map
dependenciesMap) {
+
+ List tmpList = new ArrayList(allNestedSymbols);
+
+ ordered: for (int i = 0; i < tmpList.size(); i++) {
+ boolean swap = false;
+ for (int j = 0; j < tmpList.size(); j++) {
+ String symbolName = (String) tmpList.get(j);
+ List symbolDependencies = (List)
dependenciesMap.get(symbolName);
+ if (symbolDependencies != null && symbolDependencies.size() >
0) {
+ int max = -1;
+ for (int n = 0; n < symbolDependencies.size(); n++)
+ max = Math.max(max,
tmpList.indexOf(symbolDependencies.get(n)));
+ if (max > j) {
+ String tmp = (String) tmpList.get(j);
+ tmpList.remove(j);
+ tmpList.add(max, tmp);
+ swap = true;
+ j = max;
+ }
+ }
+
+ }
+ if (!swap)
+ break ordered;
+ }
+
+ return tmpList;
+
+ }
+
+ /**
+ * <p>Returns a List of symbols found within the <code>symbolToken</code>.
+ * The comprehensive symbol table is found in the [EMAIL PROTECTED]
ClayContext}.</p>
+ */
+ private static List findSymbols(ClayContext context, String symbolToken) {
+
+ List targetList = new ArrayList();
+
+ StringBuffer buff = new StringBuffer(symbolToken);
+ Map symbols = context.getSymbols();
+ Iterator si = symbols.entrySet().iterator();
+ boolean wasSymbolFound = false;
+ int i = buff.indexOf("@");
+ replace: while (i > -1 && si.hasNext()) {
+ Map.Entry e = (Map.Entry) si.next();
+ SymbolBean symbol = (SymbolBean) e.getValue();
+ String key = symbol.getName();
+ i = (wasSymbolFound ? buff.indexOf("@") : i);
+ if (i == -1)
+ break replace;
+
+ next: while (i > -1 && i <= (buff.length() - key.length())) {
+
+ int n = -1;
+ indexOf: for (int s = i; s <= (buff.length() - key.length());
s++) {
+ for (int c = 0; c < key.length(); c++) {
+ char skey = Character.toLowerCase(key.charAt(c));
+ char tkey = Character.toLowerCase(buff.charAt(s + c));
+ if (skey != tkey)
+ continue indexOf;
+ }
+ // match found
+ n = s;
+ break indexOf;
+ }
+
+ if (n > -1) {
+ if (!targetList.contains(key))
+ targetList.add(key);
+ i = n + key.length();
+ wasSymbolFound = true;
+ } else {
+ break next;
+ }
+ }
+
+ e = null;
+ key = null;
+ }
+ symbols = null;
+ si = null;
+
+
+ return targetList;
+ }
+
+
+
/**
* <p>
Modified:
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/CreateComponentCommand.java
URL:
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/CreateComponentCommand.java?rev=417663&r1=417662&r2=417663&view=diff
==============================================================================
---
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/CreateComponentCommand.java
(original)
+++
struts/shale/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/CreateComponentCommand.java
Tue Jun 27 21:04:20 2006
@@ -127,6 +127,10 @@
// push to context
clayContext.setSymbols(symbolTable);
+ // evaluate nested symbols; symbols having symbols as values
+ realizeSymbols(clayContext);
+
+
String id = null;
if ((id = displayElement.getId()) == null)
id = createUniqueId(facesContext);
@@ -218,6 +222,9 @@
// push to context
clayContext.setSymbols(symbolTable);
+
+ // evaluate nested symbols
+ realizeSymbols(clayContext);
}
Modified:
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/SymbolsTestCase.java
URL:
http://svn.apache.org/viewvc/struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/SymbolsTestCase.java?rev=417663&r1=417662&r2=417663&view=diff
==============================================================================
---
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/SymbolsTestCase.java
(original)
+++
struts/shale/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/SymbolsTestCase.java
Tue Jun 27 21:04:20 2006
@@ -16,6 +16,8 @@
package org.apache.shale.clay.config;
import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
import javax.faces.component.UIComponent;
@@ -23,6 +25,7 @@
import junit.framework.TestSuite;
import org.apache.commons.chain.Command;
+import org.apache.shale.clay.component.chain.AbstractCommand;
import org.apache.shale.clay.component.chain.ClayContext;
import org.apache.shale.clay.component.chain.CreateComponentCommand;
import org.apache.shale.clay.component.chain.PropertyValueCommand;
@@ -46,6 +49,93 @@
}
+ public void testNestedSymbolReplacement() {
+
+
+ Map symbols = new TreeMap();
+
+ ClayContext clayContext = new ClayContext();
+ clayContext.setFacesContext(facesContext);
+ clayContext.setSymbols(symbols);
+
+ SymbolBean symbol = this.createSymbol("@a", "@b");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@b", "@c");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@c", "@d");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@d", "test");
+ symbols.put(symbol.getName(), symbol);
+
+ AbstractCommand.realizeSymbols(clayContext);
+
+ symbol = (SymbolBean) symbols.get("@a");
+ assertNotNull(symbol);
+ assertEquals("test", symbol.getValue());
+
+ symbol = (SymbolBean) symbols.get("@b");
+ assertNotNull(symbol);
+ assertEquals("test", symbol.getValue());
+
+ symbol = (SymbolBean) symbols.get("@c");
+ assertNotNull(symbol);
+ assertEquals("test", symbol.getValue());
+
+ symbol = (SymbolBean) symbols.get("@d");
+ assertNotNull(symbol);
+ assertEquals("test", symbol.getValue());
+
+
+ symbols.clear();
+
+ symbol = this.createSymbol("@a", "@b");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@b", "@a");
+ symbols.put(symbol.getName(), symbol);
+
+ AbstractCommand.realizeSymbols(clayContext);
+
+ symbol = (SymbolBean) symbols.get("@a");
+ assertNotNull(symbol);
+ assertEquals("@a", symbol.getValue());
+
+ symbol = (SymbolBean) symbols.get("@b");
+ assertNotNull(symbol);
+ assertEquals("@a", symbol.getValue());
+
+
+
+ symbols.clear();
+
+ symbol = this.createSymbol("@foo", "@[EMAIL PROTECTED]");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@xbeanx", "@a");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@xpropertyx", "@b");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@a", "foo");
+ symbols.put(symbol.getName(), symbol);
+
+ symbol = this.createSymbol("@b", "bar");
+ symbols.put(symbol.getName(), symbol);
+
+ AbstractCommand.realizeSymbols(clayContext);
+
+ symbol = (SymbolBean) symbols.get("@foo");
+ assertNotNull(symbol);
+ assertEquals("foo.bar", symbol.getValue());
+
+ }
+
+
+
public void testGenericPropertyCommand () throws Exception {
javax.faces.component.html.HtmlOutputText child =
(javax.faces.component.html.HtmlOutputText)
facesContext.getApplication().createComponent("javax.faces.HtmlOutputText");