hlship 2004/09/01 06:17:38
Modified: framework/src/java/org/apache/hivemind/internal
RegistryInfrastructure.java Module.java
framework/src/java/org/apache/hivemind/impl ModuleImpl.java
RegistryImpl.java
. status.xml
src/documentation/content/xdocs configurations.xml
Added: framework/src/java/org/apache/hivemind/impl
SymbolExpander.java
framework/src/test/org/apache/hivemind/impl
TestSymbolExpander.java
Log:
[HIVEMIND-47] Allow symbols to be escaped rather than expanded.
Revision Changes Path
1.6 +2 -6
jakarta-hivemind/framework/src/java/org/apache/hivemind/internal/RegistryInfrastructure.java
Index: RegistryInfrastructure.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/internal/RegistryInfrastructure.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- RegistryInfrastructure.java 25 Aug 2004 22:42:24 -0000 1.5
+++ RegistryInfrastructure.java 1 Sep 2004 13:17:37 -0000 1.6
@@ -19,6 +19,7 @@
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.Location;
+import org.apache.hivemind.SymbolSource;
import org.apache.hivemind.schema.Translator;
/**
@@ -28,7 +29,7 @@
*
* @author Howard Lewis Ship
*/
-public interface RegistryInfrastructure
+public interface RegistryInfrastructure extends SymbolSource
{
/**
* Obtains a service from the registry. Typically, what's returned is a
proxy,
@@ -94,11 +95,6 @@
*/
public String expandSymbols(String input, Location location);
-
- /**
- * Returns the value for a symbol, or null if not known.
- */
- public String getSymbolValue(String symbol);
/**
* Returns a named service-model factory
1.7 +2 -6
jakarta-hivemind/framework/src/java/org/apache/hivemind/internal/Module.java
Index: Module.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/internal/Module.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Module.java 25 Aug 2004 22:42:24 -0000 1.6
+++ Module.java 1 Sep 2004 13:17:37 -0000 1.7
@@ -22,6 +22,7 @@
import org.apache.hivemind.Locatable;
import org.apache.hivemind.Location;
import org.apache.hivemind.Messages;
+import org.apache.hivemind.SymbolSource;
import org.apache.hivemind.schema.Translator;
/**
@@ -39,7 +40,7 @@
*
* @author Howard Lewis Ship
*/
-public interface Module extends Locatable
+public interface Module extends Locatable, SymbolSource
{
/**
* Returns the unique identifier for this module.
@@ -130,9 +131,4 @@
*/
public ErrorHandler getErrorHandler();
-
- /**
- * Returns the value for a symbol, or null if not known.
- */
- public String getSymbolValue(String symbol);
}
1.11 +2 -2
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ModuleImpl.java
Index: ModuleImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ModuleImpl.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- ModuleImpl.java 25 Aug 2004 22:42:24 -0000 1.10
+++ ModuleImpl.java 1 Sep 2004 13:17:37 -0000 1.11
@@ -135,9 +135,9 @@
return _registry.getErrorHander();
}
- public String getSymbolValue(String symbol)
+ public String valueForSymbol(String symbol)
{
- return _registry.getSymbolValue(symbol);
+ return _registry.valueForSymbol(symbol);
}
}
1.20 +5 -153
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/RegistryImpl.java
Index: RegistryImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/RegistryImpl.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- RegistryImpl.java 25 Aug 2004 22:42:24 -0000 1.19
+++ RegistryImpl.java 1 Sep 2004 13:17:37 -0000 1.20
@@ -84,12 +84,16 @@
private ThreadEventNotifier _threadEventNotifier;
private TranslatorManager _translatorManager;
+ private SymbolExpander _expander;
+
public RegistryImpl(ErrorHandler errorHandler, Locale locale)
{
_errorHandler = errorHandler;
_locale = locale;
_translatorManager = new TranslatorManager(this, errorHandler);
+
+ _expander = new SymbolExpander(_errorHandler, this);
}
public Locale getLocale()
@@ -193,161 +197,9 @@
return builder.toString();
}
- private static final int STATE_START = 0;
- private static final int STATE_DOLLAR = 1;
- private static final int STATE_COLLECT_SYMBOL_NAME = 2;
-
- /**
- *
- * Note: a little cut-n-paste from [EMAIL PROTECTED]
org.apache.tapestry.script.AbstractTokenRule}.
- */
public String expandSymbols(String text, Location location)
{
- StringBuffer result = new StringBuffer(text.length());
- char[] buffer = text.toCharArray();
- int state = STATE_START;
- int blockStart = 0;
- int blockLength = 0;
- int symbolStart = -1;
- int symbolLength = 0;
- int i = 0;
- int braceDepth = 0;
- boolean anySymbols = false;
-
- while (i < buffer.length)
- {
- char ch = buffer[i];
-
- switch (state)
- {
- case STATE_START :
-
- if (ch == '$')
- {
- state = STATE_DOLLAR;
- i++;
- continue;
- }
-
- blockLength++;
- i++;
- continue;
-
- case STATE_DOLLAR :
-
- if (ch == '{')
- {
- state = STATE_COLLECT_SYMBOL_NAME;
- i++;
-
- symbolStart = i;
- symbolLength = 0;
- braceDepth = 1;
-
- continue;
- }
-
- // The '$' was just what it was, not the start of a ${}
expression
- // block, so include it as part of the static text block.
-
- blockLength++;
-
- state = STATE_START;
- continue;
-
- case STATE_COLLECT_SYMBOL_NAME :
-
- if (ch != '}')
- {
- if (ch == '{')
- braceDepth++;
-
- i++;
- symbolLength++;
- continue;
- }
-
- braceDepth--;
-
- if (braceDepth > 0)
- {
- i++;
- symbolLength++;
- continue;
- }
-
- // Hit the closing brace of a symbol.
-
- // Degenerate case: the string "${}".
-
- if (symbolLength == 0)
- blockLength += 3;
-
- // Append anything up to the start of the sequence (this
is static
- // text between symbol references).
-
- if (blockLength > 0)
- result.append(buffer, blockStart, blockLength);
-
- if (symbolLength > 0)
- {
- String variableName =
- text.substring(symbolStart, symbolStart +
symbolLength);
-
- result.append(expandSymbol(variableName, location));
-
- anySymbols = true;
- }
-
- i++;
- blockStart = i;
- blockLength = 0;
-
- // And drop into state start
-
- state = STATE_START;
-
- continue;
- }
-
- }
-
- // If get this far without seeing any variables, then just pass
- // the input back.
-
- if (!anySymbols)
- return text;
-
- // OK, to handle the end. Couple of degenerate cases where
- // a ${...} was incomplete, so we adust the block length.
-
- if (state == STATE_DOLLAR)
- blockLength++;
-
- if (state == STATE_COLLECT_SYMBOL_NAME)
- blockLength += symbolLength + 2;
-
- if (blockLength > 0)
- result.append(buffer, blockStart, blockLength);
-
- return result.toString();
- }
-
- private String expandSymbol(String name, Location location)
- {
- String value = valueForSymbol(name);
-
- if (value != null)
- return value;
-
- _errorHandler.error(LOG, ImplMessages.noSuchSymbol(name), location,
null);
-
- return "${" + name + "}";
- }
-
- public String getSymbolValue(String name)
- {
- return valueForSymbol(name);
+ return _expander.expandSymbols(text, location);
}
public String valueForSymbol(String name)
1.1
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/SymbolExpander.java
Index: SymbolExpander.java
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.hivemind.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.Location;
import org.apache.hivemind.SymbolSource;
/**
* A simple parser used to identify symbols in a string and expand them via
* a [EMAIL PROTECTED] org.apache.hivemind.SymbolSource}.
*
* @author Howard Lewis Ship
*/
public class SymbolExpander
{
private ErrorHandler _errorHandler;
private SymbolSource _source;
public SymbolExpander(ErrorHandler handler, SymbolSource source)
{
_errorHandler = handler;
_source = source;
}
private static final Log LOG = LogFactory.getLog(SymbolExpander.class);
private static final int STATE_START = 0;
private static final int STATE_DOLLAR = 1;
private static final int STATE_COLLECT_SYMBOL_NAME = 2;
/**
* <p>Identifies symbols in the text and expands them, using the
* [EMAIL PROTECTED] SymbolSource}. Returns the modified text. May
return text if text
* does not contain any symbols.
*
* @param text the text to scan
* @param location the location to report errors (undefined symbols)
*
* Note: a little cut-n-paste from [EMAIL PROTECTED]
org.apache.tapestry.script.AbstractTokenRule}.
*/
public String expandSymbols(String text, Location location)
{
StringBuffer result = new StringBuffer(text.length());
char[] buffer = text.toCharArray();
int state = STATE_START;
int blockStart = 0;
int blockLength = 0;
int symbolStart = -1;
int symbolLength = 0;
int i = 0;
int braceDepth = 0;
boolean anySymbols = false;
while (i < buffer.length)
{
char ch = buffer[i];
switch (state)
{
case STATE_START :
if (ch == '$')
{
state = STATE_DOLLAR;
i++;
continue;
}
blockLength++;
i++;
continue;
case STATE_DOLLAR :
if (ch == '{')
{
state = STATE_COLLECT_SYMBOL_NAME;
i++;
symbolStart = i;
symbolLength = 0;
braceDepth = 1;
continue;
}
// Any time two $$ appear, it is collapsed down to a
single $,
// but the next character is passed through
un-interpreted (even if it
// is a brace).
if (ch == '$')
{
// This is effectively a symbol, meaning that the input
string
// will not equal the output string.
anySymbols = true;
if (blockLength > 0)
result.append(buffer,
blockStart, blockLength);
result.append(ch);
i++;
blockStart = i;
blockLength = 0;
state = STATE_START;
continue;
}
// The '$' was just what it was, not the start of a ${}
expression
// block, so include it as part of the static text block.
blockLength++;
state = STATE_START;
continue;
case STATE_COLLECT_SYMBOL_NAME :
if (ch != '}')
{
if (ch == '{')
braceDepth++;
i++;
symbolLength++;
continue;
}
braceDepth--;
if (braceDepth > 0)
{
i++;
symbolLength++;
continue;
}
// Hit the closing brace of a symbol.
// Degenerate case: the string "${}".
if (symbolLength == 0)
blockLength += 3;
// Append anything up to the start of the sequence (this
is static
// text between symbol references).
if (blockLength > 0)
result.append(buffer, blockStart, blockLength);
if (symbolLength > 0)
{
String variableName =
text.substring(symbolStart, symbolStart +
symbolLength);
result.append(expandSymbol(variableName, location));
anySymbols = true;
}
i++;
blockStart = i;
blockLength = 0;
// And drop into state start
state = STATE_START;
continue;
}
}
// If get this far without seeing any variables, then just pass
// the input back.
if (!anySymbols)
return text;
// OK, to handle the end. Couple of degenerate cases where
// a ${...} was incomplete, so we adust the block length.
if (state == STATE_DOLLAR)
blockLength++;
if (state == STATE_COLLECT_SYMBOL_NAME)
blockLength += symbolLength + 2;
if (blockLength > 0)
result.append(buffer, blockStart, blockLength);
return result.toString();
}
private String expandSymbol(String name, Location location)
{
String value = _source.valueForSymbol(name);
if (value != null)
return value;
_errorHandler.error(LOG, ImplMessages.noSuchSymbol(name), location,
null);
return "${" + name + "}";
}
}
1.56 +3 -0 jakarta-hivemind/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/status.xml,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- status.xml 31 Aug 2004 20:02:13 -0000 1.55
+++ status.xml 1 Sep 2004 13:17:37 -0000 1.56
@@ -37,6 +37,9 @@
<action type="fix" dev="HLS" fixes-bug="HIVEMIND-48">
Fix class loader issues concerning fabricated classes in different
modules.
</action>
+ <action type="fix" dev="HLS" fixes-bug="HIVEMIND-47">
+ Allow symbols to be escaped rather than expanded.
+ </action>
</release>
1.9 +6 -0
jakarta-hivemind/src/documentation/content/xdocs/configurations.xml
Index: configurations.xml
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/src/documentation/content/xdocs/configurations.xml,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- configurations.xml 17 Aug 2004 12:33:22 -0000 1.8
+++ configurations.xml 1 Sep 2004 13:17:37 -0000 1.9
@@ -210,6 +210,12 @@
<code>config.dir</code> and
<code>config.file</code> symbols will be
converted to strings first, then whatever rules
are in place to convert
the <code>value</code> element into a Java
object will be executed.</p>
+ <note>
+ If you contribute text that includes symbols that you do
<strong>not</strong> want to be expanded
+ then you must add an extra dollar sign to the false symbol. This
is to support legacy data that was
+ already using the HiveMind symbol notation for its own, internal
purposes. For example, <code>foo $${bar} baz</code> will be
+ expanded into the text <code>foo ${bar} baz</code>.
+ </note>
<section>
<title>Symbol Sources</title>
<p>This begs the question: where do symbol
values come from? The answser
1.1
jakarta-hivemind/framework/src/test/org/apache/hivemind/impl/TestSymbolExpander.java
Index: TestSymbolExpander.java
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.hivemind.impl;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.Location;
import org.apache.hivemind.SymbolSource;
import org.apache.hivemind.test.HiveMindTestCase;
import org.easymock.MockControl;
/**
* Tests for [EMAIL PROTECTED] org.apache.hivemind.impl.SymbolExpander}.
*
* @author Howard Lewis Ship
* @since 3.1
*/
public class TestSymbolExpander extends HiveMindTestCase
{
private class SymbolSourceFixture implements SymbolSource
{
public String valueForSymbol(String name)
{
return name.toUpperCase();
}
}
private void attempt(String expected, String text)
{
SymbolExpander e = new SymbolExpander(null, new
SymbolSourceFixture());
String actual = e.expandSymbols(text, null);
assertEquals(expected, actual);
}
public void testSimple()
{
attempt("Now is the TIME", "Now is the ${time}");
}
public void testNoSymbols()
{
attempt("No symbols in here", "No symbols in here");
}
public void testFalseStart()
{
attempt("The cost of the ITEM is $1,000.", "The cost of the ${item}
is $1,000.");
}
public void testNestedBraces()
{
attempt("Nested {BRACES}", "Nested ${{braces}}");
}
public void testEmptySymbol()
{
attempt("An empty ${} symbol", "An empty ${} symbol");
}
public void testTrailingDollar()
{
attempt("SYMBOL Ends with $", "${symbol} Ends with $");
}
public void testEndsWithPartialSymbol()
{
attempt("SYMBOL Ends with ${partial", "${symbol} Ends with
${partial");
}
public void testMissingSymbol()
{
ErrorHandler eh = (ErrorHandler) newMock(ErrorHandler.class);
Location l = fabricateLocation(2828);
MockControl control = newControl(SymbolSource.class);
SymbolSource source = (SymbolSource) control.getMock();
// Training
source.valueForSymbol("symbol");
control.setReturnValue(null);
eh.error(
LogFactory.getLog(SymbolExpander.class),
ImplMessages.noSuchSymbol("symbol"),
l,
null);
replayControls();
SymbolExpander e = new SymbolExpander(eh, source);
String actual = e.expandSymbols("Unknown ${symbol}", l);
assertEquals("Unknown ${symbol}", actual);
verifyControls();
}
public void testEscaped()
{
attempt("This is a SYMBOL, this is ${not}.", "This is a ${symbol},
this is $${not}.");
}
public void testEscapedAtStart()
{
attempt("${not-a-symbol}", "$${not-a-symbol}");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]