summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOComponent.java
diff options
context:
space:
mode:
Diffstat (limited to 'projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOComponent.java')
-rw-r--r--projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOComponent.java2118
1 files changed, 942 insertions, 1176 deletions
diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOComponent.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOComponent.java
index 20d8b0a..c99768c 100644
--- a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOComponent.java
+++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/WOComponent.java
@@ -42,1271 +42,1037 @@ import net.wotonomy.foundation.NSMutableDictionary;
import net.wotonomy.foundation.NSSelector;
/**
-* Pure java implementation of WOComponent.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 905 $
-*/
-public class WOComponent
- extends WOElement
- implements WOActionResults,
- net.wotonomy.control.EOKeyValueCodingAdditions,
- net.wotonomy.control.EOKeyValueCoding
-{
+ * Pure java implementation of WOComponent.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 905 $
+ */
+public class WOComponent extends WOElement implements WOActionResults, net.wotonomy.control.EOKeyValueCodingAdditions,
+ net.wotonomy.control.EOKeyValueCoding {
WOElement rootElement;
-
- private static final String DIRECTORY_SUFFIX = ".wo";
- private static final String TEMPLATE_SUFFIX = ".html";
- private static final String DECLARATION_SUFFIX = ".wod";
-
- private static final String OPEN_TAG = "webobject";
- private static final String CLOSE_TAG = "/webobject";
- private static final String NAME_KEY = "name";
-
- protected transient WOContext context; // don't persist
- protected boolean cachingEnabled;
- protected WOElement template;
- protected WOComponent parent;
+
+ private static final String DIRECTORY_SUFFIX = ".wo";
+ private static final String TEMPLATE_SUFFIX = ".html";
+ private static final String DECLARATION_SUFFIX = ".wod";
+
+ private static final String OPEN_TAG = "webobject";
+ private static final String CLOSE_TAG = "/webobject";
+ private static final String NAME_KEY = "name";
+
+ protected transient WOContext context; // don't persist
+ protected boolean cachingEnabled;
+ protected WOElement template;
+ protected WOComponent parent;
+
+ /**
+ * Default constructor. Deprecated in latest spec.
+ */
+ public WOComponent() {
+ parent = null;
+ cachingEnabled = true;
+ template = null;
+ }
+
+ /**
+ * Constructor specifying a context.
+ */
+ public WOComponent(WOContext aContext) {
+ this();
+ context = aContext;
+ }
+
+ /**
+ * Returns the name of the component, which is usually just the class name.
+ */
+ public String name() {
+ return justTheClassName();
+ }
/**
- * Default constructor. Deprecated in latest spec.
- */
- public WOComponent ()
- {
- parent = null;
- cachingEnabled = true;
- template = null;
- }
-
- /**
- * Constructor specifying a context.
- */
- public WOComponent( WOContext aContext )
- {
- this();
- context = aContext;
- }
-
+ * Returns the system-dependent file path to the current component directory,
+ * including the ".wo" extension.
+ */
+ public String path() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
/**
- * Returns the name of the component, which is usually just the class name.
- */
- public String name ()
- {
- return justTheClassName();
- }
-
- /**
- * Returns the system-dependent file path to the current component
- * directory, including the ".wo" extension.
- */
- public String path ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
+ * Returns the URL for this component, relative to the server's document root on
+ * the server's file system. This is not an http url.
+ */
+ public String baseURL() {
+ throw new RuntimeException("Not implemented yet.");
+ }
/**
- * Returns the URL for this component, relative to the server's
- * document root on the server's file system.
- * This is not an http url.
- */
- public String baseURL ()
- {
- throw new RuntimeException( "Not implemented yet." );
- }
+ * Returns the name of the framework that contains this component, or null if
+ * the component does not belong to a framework. This currently returns the
+ * package path of the class, or null if it does not belong to a package.
+ */
+ public String frameworkName() {
+ return justTheResourcePath();
+ }
/**
- * Returns the name of the framework that contains this component,
- * or null if the component does not belong to a framework.
- * This currently returns the package path of the class, or
- * null if it does not belong to a package.
- */
- public String frameworkName ()
- {
- return justTheResourcePath();
- }
-
- /**
- * Sets whether templates are cached. If true, templates will
- * only be read once per application lifetime. Otherwise, templates
- * will be read each time this class is instantiated. Defaults to false.
- */
- public void setCachingEnabled (boolean enabled)
- {
+ * Sets whether templates are cached. If true, templates will only be read once
+ * per application lifetime. Otherwise, templates will be read each time this
+ * class is instantiated. Defaults to false.
+ */
+ public void setCachingEnabled(boolean enabled) {
cachingEnabled = enabled;
}
- /**
- * Returns whether templates are cached. If true, templates are
- * read once per application lifetime. Otherwise, templates are
- * read each time this class is instantiated.
- */
- public boolean isCachingEnabled ()
- {
- return cachingEnabled && WOApplication.application().isCachingEnabled();
- }
-
- /**
- * Returns the root of the tree of elements produced by parsing
- * the templates in the component directory for this component.
- */
- public WOElement template()
- {
- return template;
- }
-
- /**
- * Returns the root of the tree of elements produced by parsing
- * the templates in the component directory for the named component.
- * @deprecated Use template() instead.
- */
- public WOElement templateWithName(String aComponentName)
- {
- return templateWithName( aComponentName, null );
- }
-
- /**
- * Returns the root of the tree of elements produced by parsing
- * the templates in the component directory for the named component.
- */
- WOElement templateWithName(String aComponentName, String aFramework)
- {
- NSArray languages = null;
- WOContext context = context();
- if ( context != null )
- {
- languages = context.request().browserLanguages();
- }
- WOElement result = templateWithHTMLString(
- readTemplateResource( aComponentName, aFramework, TEMPLATE_SUFFIX, languages ),
- readTemplateResource( aComponentName, aFramework, DECLARATION_SUFFIX, languages ),
- languages );
- if ( result == null )
- {
- System.out.println( "WOComponent.templateWithName: failed for " + aComponentName );
- }
- return result;
- }
-
- /**
- * Returns the root of the tree of elements produced by parsing
- * the specfified HTML string and bindings declaration string.
- * Note: language list is currently ignored.
- */
- public static WOElement templateWithHTMLString (
- String anHTMLString, String aDeclaration, List aLanguageList)
- {
- if ( anHTMLString == null ) return null;
- WOElement result = null;
- try
- {
- NSDictionary bindings = processDeclaration( aDeclaration );
- List elements = new LinkedList();
- int index = processTemplate( elements, anHTMLString, 0, bindings, aLanguageList );
- if ( index == -1 )
- {
- if ( elements.size() == 1 )
- {
- result = (WOElement) elements.get(0);
- }
- else
- {
- result = new WOParentElement( elements );
- }
- }
- else // entire template did not process
- {
- throw new RuntimeException( "No closing tag: " + anHTMLString.substring( index ) );
- }
- }
- catch ( Exception exc )
- {
- exc.printStackTrace();
- }
+ /**
+ * Returns whether templates are cached. If true, templates are read once per
+ * application lifetime. Otherwise, templates are read each time this class is
+ * instantiated.
+ */
+ public boolean isCachingEnabled() {
+ return cachingEnabled && WOApplication.application().isCachingEnabled();
+ }
+
+ /**
+ * Returns the root of the tree of elements produced by parsing the templates in
+ * the component directory for this component.
+ */
+ public WOElement template() {
+ return template;
+ }
+
+ /**
+ * Returns the root of the tree of elements produced by parsing the templates in
+ * the component directory for the named component.
+ *
+ * @deprecated Use template() instead.
+ */
+ public WOElement templateWithName(String aComponentName) {
+ return templateWithName(aComponentName, null);
+ }
+
+ /**
+ * Returns the root of the tree of elements produced by parsing the templates in
+ * the component directory for the named component.
+ */
+ WOElement templateWithName(String aComponentName, String aFramework) {
+ NSArray languages = null;
+ WOContext context = context();
+ if (context != null) {
+ languages = context.request().browserLanguages();
+ }
+ WOElement result = templateWithHTMLString(
+ readTemplateResource(aComponentName, aFramework, TEMPLATE_SUFFIX, languages),
+ readTemplateResource(aComponentName, aFramework, DECLARATION_SUFFIX, languages), languages);
+ if (result == null) {
+ System.out.println("WOComponent.templateWithName: failed for " + aComponentName);
+ }
return result;
- }
-
- /**
- * Called at the beginning of a request-response cycle.
- * Override to perform any necessary initialization.
- * This implementation does nothing.
- */
- public void awake ()
- {
- }
-
- /**
- * Package access only. Called to initialize the component with
- * the proper context before the start of the request-response cycle.
- * If the context has a current component, that component becomes
- * this component's parent.
- */
- void ensureAwakeInContext (WOContext aContext)
- {
+ }
+
+ /**
+ * Returns the root of the tree of elements produced by parsing the specfified
+ * HTML string and bindings declaration string. Note: language list is currently
+ * ignored.
+ */
+ public static WOElement templateWithHTMLString(String anHTMLString, String aDeclaration, List aLanguageList) {
+ if (anHTMLString == null)
+ return null;
+ WOElement result = null;
+ try {
+ NSDictionary bindings = processDeclaration(aDeclaration);
+ List elements = new LinkedList();
+ int index = processTemplate(elements, anHTMLString, 0, bindings, aLanguageList);
+ if (index == -1) {
+ if (elements.size() == 1) {
+ result = (WOElement) elements.get(0);
+ } else {
+ result = new WOParentElement(elements);
+ }
+ } else // entire template did not process
+ {
+ throw new RuntimeException("No closing tag: " + anHTMLString.substring(index));
+ }
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * Called at the beginning of a request-response cycle. Override to perform any
+ * necessary initialization. This implementation does nothing.
+ */
+ public void awake() {
+ }
+
+ /**
+ * Package access only. Called to initialize the component with the proper
+ * context before the start of the request-response cycle. If the context has a
+ * current component, that component becomes this component's parent.
+ */
+ void ensureAwakeInContext(WOContext aContext) {
context = aContext;
parent = aContext.parent();
- if ( template == null )
- {
- template = templateWithName( name(), frameworkName() );
- }
- if ( template != null )
- {
- template.ensureAwakeInContext( aContext );
- }
- awake();
- }
-
- public void takeValuesFromRequest (WORequest aRequest, WOContext aContext)
- {
- if ( synchronizesVariablesWithBindings() )
- {
- pullValuesFromParent();
- if ( template != null )
- {
- template.takeValuesFromRequest( aRequest, aContext );
- }
- pushValuesToParent();
- }
- else
- if ( template != null )
- {
- template.takeValuesFromRequest( aRequest, aContext );
- }
- }
-
- public WOActionResults invokeAction (WORequest aRequest, WOContext aContext)
- {
- WOActionResults result = null;
- if ( synchronizesVariablesWithBindings() )
- {
- pullValuesFromParent();
- if ( template != null )
- {
- result = template.invokeAction( aRequest, aContext );
- }
- pushValuesToParent();
- }
- else
- if ( template != null )
- {
- result = template.invokeAction( aRequest, aContext );
- }
+ if (template == null) {
+ template = templateWithName(name(), frameworkName());
+ }
+ if (template != null) {
+ template.ensureAwakeInContext(aContext);
+ }
+ awake();
+ }
+
+ public void takeValuesFromRequest(WORequest aRequest, WOContext aContext) {
+ if (synchronizesVariablesWithBindings()) {
+ pullValuesFromParent();
+ if (template != null) {
+ template.takeValuesFromRequest(aRequest, aContext);
+ }
+ pushValuesToParent();
+ } else if (template != null) {
+ template.takeValuesFromRequest(aRequest, aContext);
+ }
+ }
+
+ public WOActionResults invokeAction(WORequest aRequest, WOContext aContext) {
+ WOActionResults result = null;
+ if (synchronizesVariablesWithBindings()) {
+ pullValuesFromParent();
+ if (template != null) {
+ result = template.invokeAction(aRequest, aContext);
+ }
+ pushValuesToParent();
+ } else if (template != null) {
+ result = template.invokeAction(aRequest, aContext);
+ }
return result;
- }
-
- public void appendToResponse (WOResponse aResponse, WOContext aContext)
- {
- if ( synchronizesVariablesWithBindings() )
- {
- pullValuesFromParent();
- if ( template != null )
- {
- template.appendToResponse( aResponse, aContext );
- }
- pushValuesToParent();
- }
- else
- if ( template != null )
- {
- template.appendToResponse( aResponse, aContext );
- }
- context = null;
- }
-
- /**
- * Called at the end of a request-response cycle.
- * Override to perform any necessary clean-up.
- * This implementation does nothing.
- */
- public void sleep ()
- {
- }
-
- /**
- * Generates a WOResponse and calls appendToResponse() on it.
- */
- public WOResponse generateResponse ()
- {
- WOResponse response = new WOResponse();
- WOContext context = context();
- appendToResponse( response, context ); // nulls out context
- context.session().savePage( this ); //?is this the right place for this?
- return response;
- }
+ }
+
+ public void appendToResponse(WOResponse aResponse, WOContext aContext) {
+ if (synchronizesVariablesWithBindings()) {
+ pullValuesFromParent();
+ if (template != null) {
+ template.appendToResponse(aResponse, aContext);
+ }
+ pushValuesToParent();
+ } else if (template != null) {
+ template.appendToResponse(aResponse, aContext);
+ }
+ context = null;
+ }
+
+ /**
+ * Called at the end of a request-response cycle. Override to perform any
+ * necessary clean-up. This implementation does nothing.
+ */
+ public void sleep() {
+ }
/**
- * Returns this component's parent component, or null if none.
- */
- public WOComponent parent()
- {
- return parent;
- }
-
- /**
- * Invokes the specified action on this component's parent.
- * Variables will be synchronized when this method returns.
- */
- public WOActionResults performParentAction(String anAction)
- {
- WOActionResults result = parent().performAction( anAction );
- if ( synchronizesVariablesWithBindings() )
- {
- pullValuesFromParent();
- }
- return result;
- }
-
- /**
- * Invokes the specified action on this component.
- */
- WOActionResults performAction( String anAction )
- {
- try
- {
- return (WOActionResults) NSSelector.invoke( anAction, this );
+ * Generates a WOResponse and calls appendToResponse() on it.
+ */
+ public WOResponse generateResponse() {
+ WOResponse response = new WOResponse();
+ WOContext context = context();
+ appendToResponse(response, context); // nulls out context
+ context.session().savePage(this); // ?is this the right place for this?
+ return response;
+ }
+
+ /**
+ * Returns this component's parent component, or null if none.
+ */
+ public WOComponent parent() {
+ return parent;
+ }
+
+ /**
+ * Invokes the specified action on this component's parent. Variables will be
+ * synchronized when this method returns.
+ */
+ public WOActionResults performParentAction(String anAction) {
+ WOActionResults result = parent().performAction(anAction);
+ if (synchronizesVariablesWithBindings()) {
+ pullValuesFromParent();
}
- catch ( NoSuchMethodException exc )
- {
+ return result;
+ }
+
+ /**
+ * Invokes the specified action on this component.
+ */
+ WOActionResults performAction(String anAction) {
+ try {
+ return (WOActionResults) NSSelector.invoke(anAction, this);
+ } catch (NoSuchMethodException exc) {
// returns below
- }
- catch ( InvocationTargetException exc )
- {
+ } catch (InvocationTargetException exc) {
Throwable t = exc.getTargetException();
- exc.printStackTrace();
- throw new RuntimeException( t.toString() );
+ exc.printStackTrace();
+ throw new RuntimeException(t.toString());
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ throw new RuntimeException(exc.toString());
}
- catch ( Exception exc )
- {
- exc.printStackTrace();
- throw new RuntimeException( exc.toString() );
+ return null;
+ }
+
+ /**
+ * Called before each phase of the request-response cycle, if
+ * synchronizesVariablesWithBindings is true and the component is not stateless.
+ */
+ public void pullValuesFromParent() {
+ if (associations == null)
+ return;
+ String key;
+ Enumeration e = associations.keyEnumerator();
+ while (e.hasMoreElements()) {
+ key = e.nextElement().toString();
+ takeValueForKey(valueForBinding(key), key);
+ }
+ }
+
+ /**
+ * Called after each phase of the request-response cycle, if
+ * synchronizesVariablesWithBindings is true and the component is not stateless.
+ */
+ public void pushValuesToParent() {
+ if (associations == null)
+ return;
+ String key;
+ Enumeration e = associations.keyEnumerator();
+ while (e.hasMoreElements()) {
+ key = e.nextElement().toString();
+ setValueForBinding(valueForKey(key), key);
}
- return null;
- }
-
- /**
- * Called before each phase of the request-response cycle,
- * if synchronizesVariablesWithBindings is true and the
- * component is not stateless.
- */
- public void pullValuesFromParent()
- {
- if ( associations == null ) return;
- String key;
- Enumeration e = associations.keyEnumerator();
- while ( e.hasMoreElements() )
- {
- key = e.nextElement().toString();
- takeValueForKey( valueForBinding( key ), key );
- }
- }
-
- /**
- * Called after each phase of the request-response cycle,
- * if synchronizesVariablesWithBindings is true and the
- * component is not stateless.
- */
- public void pushValuesToParent()
- {
- if ( associations == null ) return;
- String key;
- Enumeration e = associations.keyEnumerator();
- while ( e.hasMoreElements() )
- {
- key = e.nextElement().toString();
- setValueForBinding( valueForKey( key ), key );
- }
- }
-
- /**
- * Returns whether this component should be considered stateless.
- * Stateless components are shared between sessions to conserve memory.
- * This implementation returns false; override to return true.
- */
- public boolean isStateless()
- {
- return false;
- }
-
- /**
- * Called only on stateless components to tell themselves to reset
- * themselves for another invocation using a different context.
- * This implementation does nothing.
- */
- public void reset()
- {
- // does nothing
- }
-
- /**
- * Returns the application containing this instance of the class.
- */
- public WOApplication application ()
- {
- return context.application();
- }
-
- /**
- * Returns whether a session has been created for this user.
- */
- public boolean hasSession ()
- {
- return context.hasSession();
- }
-
- /**
- * Returns the current session object, creating it if it doesn't exist.
- */
- public WOSession session ()
- {
- return context.session();
- }
+ }
+
+ /**
+ * Returns whether this component should be considered stateless. Stateless
+ * components are shared between sessions to conserve memory. This
+ * implementation returns false; override to return true.
+ */
+ public boolean isStateless() {
+ return false;
+ }
+
+ /**
+ * Called only on stateless components to tell themselves to reset themselves
+ * for another invocation using a different context. This implementation does
+ * nothing.
+ */
+ public void reset() {
+ // does nothing
+ }
/**
- * Returns the current context for this component.
- */
- public WOContext context ()
- {
- return context;
- }
+ * Returns the application containing this instance of the class.
+ */
+ public WOApplication application() {
+ return context.application();
+ }
/**
- * Returns a new WOComponent with the specified name.
- * If null, returns the component named "Main".
- * If the named component doesn't exist, returns null.
- */
- public WOComponent pageWithName (String aName)
- {
- return application().pageWithName( aName, context() );
- }
+ * Returns whether a session has been created for this user.
+ */
+ public boolean hasSession() {
+ return context.hasSession();
+ }
/**
- * Called when exceptions are raised by assigning values
- * to this object. This implementation does nothing, but
- * subclasses may override to do something useful.
- */
- public void validationFailedWithException (
- Throwable anException, Object aValue, String aPath)
- {
- // does nothing
- }
+ * Returns the current session object, creating it if it doesn't exist.
+ */
+ public WOSession session() {
+ return context.session();
+ }
/**
- * Called on the component that represents the requested page.
- * Override to return logging information specific to your
- * component. This implementation returns the component's name.
- */
- public String descriptionForResponse (
- WOResponse aResponse, WOContext aContext)
- {
- return name();
- }
+ * Returns the current context for this component.
+ */
+ public WOContext context() {
+ return context;
+ }
/**
- * Returns true if this component should get and set values
- * in its parent. This implementation returns true.
- * Override to create a component that does not automatically
- * synchronize bindings with its parent, useful if you wish
- * to handle synchronization manually.
- */
- public boolean synchronizesVariablesWithBindings ()
- {
- return true;
- }
-
- /**
- * Returns whether this component has a readable value that maps
- * to the specified binding. This implementation calls
- * hasBinding(aBinding).
- */
- public boolean canGetValueForBinding(String aBinding)
- {
- return hasBinding( aBinding );
- }
-
- /**
- * Returns whether this component has a writable value that maps
- * to the specified binding.
- */
- public boolean canSetValueForBinding(String aBinding)
- {
- WOAssociation assoc =
- (WOAssociation)associations.objectForKey(aBinding);
- if (assoc != null)
- {
- if ( assoc.isValueSettable() ) return true;
- }
- return false;
- }
-
- /**
- * Returns whether this component has the specified binding.
- */
- public boolean hasBinding (String aBinding)
- {
- if ( associations == null ) return false;
- return associations.containsKey( aBinding );
- }
+ * Returns a new WOComponent with the specified name. If null, returns the
+ * component named "Main". If the named component doesn't exist, returns null.
+ */
+ public WOComponent pageWithName(String aName) {
+ return application().pageWithName(aName, context());
+ }
+
+ /**
+ * Called when exceptions are raised by assigning values to this object. This
+ * implementation does nothing, but subclasses may override to do something
+ * useful.
+ */
+ public void validationFailedWithException(Throwable anException, Object aValue, String aPath) {
+ // does nothing
+ }
+
+ /**
+ * Called on the component that represents the requested page. Override to
+ * return logging information specific to your component. This implementation
+ * returns the component's name.
+ */
+ public String descriptionForResponse(WOResponse aResponse, WOContext aContext) {
+ return name();
+ }
/**
- * Returns the value for the specified binding for this component.
- * The parent component is expected to have set the binding for
- * this component. If no such binding exists, the binding is
- * treated as a property is and obtained using valueForKey.
- * If the property is not found, this method returns null.
- */
- public Object valueForBinding (String aBinding)
- {
- WOComponent parent = parent();
- if ( associations != null )
- {
- WOAssociation assoc =
- (WOAssociation)associations.objectForKey(aBinding);
- if (assoc != null && parent != null)
- {
- return assoc.valueInComponent( parent );
- }
- }
- if ( parent != null )
- {
- return parent.valueForKey( aBinding );
- }
- return null;
- }
+ * Returns true if this component should get and set values in its parent. This
+ * implementation returns true. Override to create a component that does not
+ * automatically synchronize bindings with its parent, useful if you wish to
+ * handle synchronization manually.
+ */
+ public boolean synchronizesVariablesWithBindings() {
+ return true;
+ }
+
+ /**
+ * Returns whether this component has a readable value that maps to the
+ * specified binding. This implementation calls hasBinding(aBinding).
+ */
+ public boolean canGetValueForBinding(String aBinding) {
+ return hasBinding(aBinding);
+ }
+
+ /**
+ * Returns whether this component has a writable value that maps to the
+ * specified binding.
+ */
+ public boolean canSetValueForBinding(String aBinding) {
+ WOAssociation assoc = (WOAssociation) associations.objectForKey(aBinding);
+ if (assoc != null) {
+ if (assoc.isValueSettable())
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether this component has the specified binding.
+ */
+ public boolean hasBinding(String aBinding) {
+ if (associations == null)
+ return false;
+ return associations.containsKey(aBinding);
+ }
+
+ /**
+ * Returns the value for the specified binding for this component. The parent
+ * component is expected to have set the binding for this component. If no such
+ * binding exists, the binding is treated as a property is and obtained using
+ * valueForKey. If the property is not found, this method returns null.
+ */
+ public Object valueForBinding(String aBinding) {
+ WOComponent parent = parent();
+ if (associations != null) {
+ WOAssociation assoc = (WOAssociation) associations.objectForKey(aBinding);
+ if (assoc != null && parent != null) {
+ return assoc.valueInComponent(parent);
+ }
+ }
+ if (parent != null) {
+ return parent.valueForKey(aBinding);
+ }
+ return null;
+ }
/**
- * Sets the value for the specified binding for this component.
- * The parent component is expected to have set the binding
- * for this component. If no such binding exists, the binding
- * is treated as a property and is set using takeValueForKey.
- * If the property is not found, this method fails silently.
- */
- public void setValueForBinding (Object aValue, String aBinding)
- {
- if ( associations == null ) return;
-
- WOComponent parent = parent();
-
- if ( associations != null )
- {
- WOAssociation assoc =
- (WOAssociation)associations.objectForKey(aBinding);
- if (assoc != null && parent != null)
- {
- if ( assoc.isValueSettable() )
- {
- assoc.setValue( aValue, parent );
- return;
- }
- }
- }
- if ( parent != null )
- {
- parent.takeValueForKey( aValue, aBinding );
- }
- }
-
- public static void logString (String aString)
- {
- System.out.println( aString );
- }
-
- public static void debugString (String aString)
- {
- System.err.println( aString );
- }
-
- public Object valueForKeyPath (String aPath)
- {
- // currently key value coding support also handles keypaths
- return valueForKey( aPath );
- }
-
- public void takeValueForKeyPath (Object aValue, String aPath)
- {
- // currently key value coding support also handles keypaths
- takeValueForKey( aValue, aPath );
- }
-
- public NSDictionary valuesForKeys (List aKeyList)
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- public void takeValuesFromDictionary (Map aValueMap)
- {
- throw new RuntimeException( "Not implemented yet." );
- }
-
- public Object valueForKey (String aKey)
- { // System.out.println( "valueForKey: " + aKey + "->" + this );
- // handle "^" property keys
- if ( aKey.startsWith( "^" ) )
- {
- return valueForBinding( aKey.substring(1) );
- }
- return EOKeyValueCodingSupport.valueForKey( this, aKey );
- }
-
- public void takeValueForKey (Object aValue, String aKey)
- { // System.out.println( "takeValueForKey: " + aKey + " : " + aValue + "->" + this );
- // handle "^" property keys
- if ( aKey.startsWith( "^" ) )
- {
- setValueForBinding( aValue, aKey.substring(1) );
- return;
- }
- EOKeyValueCodingSupport.takeValueForKey( this, aValue, aKey );
- }
-
- public Object storedValueForKey (String aKey)
- {
- return EOKeyValueCodingSupport.storedValueForKey( this, aKey );
- }
-
- public void takeStoredValueForKey (Object aValue, String aKey)
- {
- EOKeyValueCodingSupport.takeStoredValueForKey( this, aValue, aKey );
- }
-
- public Object handleQueryWithUnboundKey (String aKey)
- {
- return EOKeyValueCodingSupport.handleQueryWithUnboundKey( this, aKey );
- }
-
- public void handleTakeValueForUnboundKey (Object aValue, String aKey)
- {
- EOKeyValueCodingSupport.handleTakeValueForUnboundKey( this, aValue, aKey );
- }
-
- public void unableToSetNullForKey (String aKey)
- {
- EOKeyValueCodingSupport.unableToSetNullForKey( this, aKey );
- }
-
- public Object validateTakeValueForKeyPath (Object aValue, String aKey)
- {
- throw new RuntimeException( "Not implemented yet." );
- }
+ * Sets the value for the specified binding for this component. The parent
+ * component is expected to have set the binding for this component. If no such
+ * binding exists, the binding is treated as a property and is set using
+ * takeValueForKey. If the property is not found, this method fails silently.
+ */
+ public void setValueForBinding(Object aValue, String aBinding) {
+ if (associations == null)
+ return;
+
+ WOComponent parent = parent();
+
+ if (associations != null) {
+ WOAssociation assoc = (WOAssociation) associations.objectForKey(aBinding);
+ if (assoc != null && parent != null) {
+ if (assoc.isValueSettable()) {
+ assoc.setValue(aValue, parent);
+ return;
+ }
+ }
+ }
+ if (parent != null) {
+ parent.takeValueForKey(aValue, aBinding);
+ }
+ }
+
+ public static void logString(String aString) {
+ System.out.println(aString);
+ }
+
+ public static void debugString(String aString) {
+ System.err.println(aString);
+ }
+
+ public Object valueForKeyPath(String aPath) {
+ // currently key value coding support also handles keypaths
+ return valueForKey(aPath);
+ }
+
+ public void takeValueForKeyPath(Object aValue, String aPath) {
+ // currently key value coding support also handles keypaths
+ takeValueForKey(aValue, aPath);
+ }
+
+ public NSDictionary valuesForKeys(List aKeyList) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ public void takeValuesFromDictionary(Map aValueMap) {
+ throw new RuntimeException("Not implemented yet.");
+ }
+ public Object valueForKey(String aKey) { // System.out.println( "valueForKey: " + aKey + "->" + this );
+ // handle "^" property keys
+ if (aKey.startsWith("^")) {
+ return valueForBinding(aKey.substring(1));
+ }
+ return EOKeyValueCodingSupport.valueForKey(this, aKey);
+ }
+
+ public void takeValueForKey(Object aValue, String aKey) { // System.out.println( "takeValueForKey: " + aKey + " : "
+ // + aValue + "->" + this );
+ // handle "^" property keys
+ if (aKey.startsWith("^")) {
+ setValueForBinding(aValue, aKey.substring(1));
+ return;
+ }
+ EOKeyValueCodingSupport.takeValueForKey(this, aValue, aKey);
+ }
+
+ public Object storedValueForKey(String aKey) {
+ return EOKeyValueCodingSupport.storedValueForKey(this, aKey);
+ }
+
+ public void takeStoredValueForKey(Object aValue, String aKey) {
+ EOKeyValueCodingSupport.takeStoredValueForKey(this, aValue, aKey);
+ }
+
+ public Object handleQueryWithUnboundKey(String aKey) {
+ return EOKeyValueCodingSupport.handleQueryWithUnboundKey(this, aKey);
+ }
+
+ public void handleTakeValueForUnboundKey(Object aValue, String aKey) {
+ EOKeyValueCodingSupport.handleTakeValueForUnboundKey(this, aValue, aKey);
+ }
+
+ public void unableToSetNullForKey(String aKey) {
+ EOKeyValueCodingSupport.unableToSetNullForKey(this, aKey);
+ }
+
+ public Object validateTakeValueForKeyPath(Object aValue, String aKey) {
+ throw new RuntimeException("Not implemented yet.");
+ }
// Template Processing
- /**
- * Takes a template string and a location to begin parsing,
- * looking only for interesting tags, and calling itself recursively
- * as necessary. Returns the index to resume parsing, or -1 if done.
- */
- static private int processTemplate(
- List elements, String template, int index,
- Map bindings, List aLanguageList )
- throws java.io.IOException
- { //System.out.println( "processTemplate: " + index );
- if ( template == null ) return -1;
-
- int start = index;
-
- while ( true )
- {
- // search for start of next tag
- start = template.indexOf( '<', start );
-
- if ( start == -1 )
- {
- // if no tags, send output and return
- elements.add( new WOStaticElement( template.substring( index ) ) );
- return -1;
- }
-
- // search for end of opening tag
- int end = template.indexOf( ">", start + 1 );
- if ( end == -1 )
- {
- // if no end to tag
- throw new RuntimeException( "No end to tag: "
- + template.substring( start ) );
- }
-
- boolean hasBody = true;
- if ( template.charAt( end - 1 ) == '/' )
- {
- // tag is standalone - no body
- end = end - 1;
- hasBody = false;
- }
-
- // search for name of tag
- int endName = start + 1;
- while ( endName < end )
- {
- if ( Character.isWhitespace(
- template.charAt(endName) ) ) break;
- endName++;
- }
-
- String name = template.substring( start + 1, endName );
-
- if ( name.toLowerCase().startsWith( OPEN_TAG ) )
- {
- // add the contents before the tag
- //System.out.println( index + " : " + start + " : " + hasBody );
- elements.add( new WOStaticElement( template.substring( index, start ) ) );
-
- // interesting tag; parse parameters
- Map params = new HashMap( 5 ); // arbitrary init length
- if ( endName < end )
- {
- // delimit by whitespace
- StringTokenizer tokens = new StringTokenizer(
- template.substring( endName+1, end ) );
- int equals;
- String token;
- String value;
- while ( tokens.hasMoreTokens() )
- {
- token = tokens.nextToken();
- equals = token.indexOf( '=' );
- if ( equals != -1 )
- {
- value = token.substring( equals+1 );
-
- if ( value.startsWith( "\"" ) )
- {
- // handle spaces within parameter names
- while ( ! value.endsWith( "\"" ) )
- {
- value = value + " " + tokens.nextToken();
- }
-
- // strip quotation marks
- if ( value.endsWith( "\"" ) )
- {
- value = value.substring( 1, value.length()-1 );
- }
- }
-
- // register key with specified value
- params.put(
- token.substring( 0, equals ).toLowerCase(), value );
-
- }
- else
- {
- // no value found, register the key name
- params.put( token.toLowerCase(), "" );
- }
- }
- }
-
- index = end + (hasBody?1:2);
-
- WOElement body = null;
- if ( hasBody )
- {
- List childElements = new LinkedList();
-
- index = processTemplate(
- childElements, template, index,
- bindings, aLanguageList );
- start = index;
-
- if ( index == -1 )
- {
- throw new RuntimeException(
- "No closing tag found: " + template.substring( end ) );
- }
-
- if ( childElements.size() == 1 )
- {
- body = (WOElement) childElements.get(0);
- }
- else
- {
- body = new WOParentElement( childElements );
- }
- }
-
- WOElement element = null;
- String nameProperty = (String) params.get( NAME_KEY );
- NSDictionary original = (NSDictionary) bindings.get( nameProperty );
- //System.out.println( nameProperty + " : " + associations );
- if ( original == null )
- {
- original = NSDictionary.EmptyDictionary;
- System.err.println( "No associations for: " + nameProperty );
- System.err.println( bindings );
- }
-
- NSDictionary associations = new NSMutableDictionary( original );
- String elementClass = (String) associations.remove( WOApplication.ELEMENT_CLASS );
-
- WOApplication application = WOApplication.application();
- element = application.dynamicElementWithName(
- elementClass, associations, body, aLanguageList );
- if ( element == null )
- {
- // unable to create element: show assocs in static element
- element = new WOStaticElement( associations.toString() );
- }
-
- //System.out.println( element );
- elements.add( element );
-
- if ( !hasBody )
- {
- start = end + 2;
- }
- }
- else
- if ( name.toLowerCase().startsWith( CLOSE_TAG ) )
- {
- // add any contents before the tag
- elements.add( new WOStaticElement( template.substring( index, start ) ) );
-
+ /**
+ * Takes a template string and a location to begin parsing, looking only for
+ * interesting tags, and calling itself recursively as necessary. Returns the
+ * index to resume parsing, or -1 if done.
+ */
+ static private int processTemplate(List elements, String template, int index, Map bindings, List aLanguageList)
+ throws java.io.IOException { // System.out.println( "processTemplate: " + index );
+ if (template == null)
+ return -1;
+
+ int start = index;
+
+ while (true) {
+ // search for start of next tag
+ start = template.indexOf('<', start);
+
+ if (start == -1) {
+ // if no tags, send output and return
+ elements.add(new WOStaticElement(template.substring(index)));
+ return -1;
+ }
+
+ // search for end of opening tag
+ int end = template.indexOf(">", start + 1);
+ if (end == -1) {
+ // if no end to tag
+ throw new RuntimeException("No end to tag: " + template.substring(start));
+ }
+
+ boolean hasBody = true;
+ if (template.charAt(end - 1) == '/') {
+ // tag is standalone - no body
+ end = end - 1;
+ hasBody = false;
+ }
+
+ // search for name of tag
+ int endName = start + 1;
+ while (endName < end) {
+ if (Character.isWhitespace(template.charAt(endName)))
+ break;
+ endName++;
+ }
+
+ String name = template.substring(start + 1, endName);
+
+ if (name.toLowerCase().startsWith(OPEN_TAG)) {
+ // add the contents before the tag
+ // System.out.println( index + " : " + start + " : " + hasBody );
+ elements.add(new WOStaticElement(template.substring(index, start)));
+
+ // interesting tag; parse parameters
+ Map params = new HashMap(5); // arbitrary init length
+ if (endName < end) {
+ // delimit by whitespace
+ StringTokenizer tokens = new StringTokenizer(template.substring(endName + 1, end));
+ int equals;
+ String token;
+ String value;
+ while (tokens.hasMoreTokens()) {
+ token = tokens.nextToken();
+ equals = token.indexOf('=');
+ if (equals != -1) {
+ value = token.substring(equals + 1);
+
+ if (value.startsWith("\"")) {
+ // handle spaces within parameter names
+ while (!value.endsWith("\"")) {
+ value = value + " " + tokens.nextToken();
+ }
+
+ // strip quotation marks
+ if (value.endsWith("\"")) {
+ value = value.substring(1, value.length() - 1);
+ }
+ }
+
+ // register key with specified value
+ params.put(token.substring(0, equals).toLowerCase(), value);
+
+ } else {
+ // no value found, register the key name
+ params.put(token.toLowerCase(), "");
+ }
+ }
+ }
+
+ index = end + (hasBody ? 1 : 2);
+
+ WOElement body = null;
+ if (hasBody) {
+ List childElements = new LinkedList();
+
+ index = processTemplate(childElements, template, index, bindings, aLanguageList);
+ start = index;
+
+ if (index == -1) {
+ throw new RuntimeException("No closing tag found: " + template.substring(end));
+ }
+
+ if (childElements.size() == 1) {
+ body = (WOElement) childElements.get(0);
+ } else {
+ body = new WOParentElement(childElements);
+ }
+ }
+
+ WOElement element = null;
+ String nameProperty = (String) params.get(NAME_KEY);
+ NSDictionary original = (NSDictionary) bindings.get(nameProperty);
+ // System.out.println( nameProperty + " : " + associations );
+ if (original == null) {
+ original = NSDictionary.EmptyDictionary;
+ System.err.println("No associations for: " + nameProperty);
+ System.err.println(bindings);
+ }
+
+ NSDictionary associations = new NSMutableDictionary(original);
+ String elementClass = (String) associations.remove(WOApplication.ELEMENT_CLASS);
+
+ WOApplication application = WOApplication.application();
+ element = application.dynamicElementWithName(elementClass, associations, body, aLanguageList);
+ if (element == null) {
+ // unable to create element: show assocs in static element
+ element = new WOStaticElement(associations.toString());
+ }
+
+ // System.out.println( element );
+ elements.add(element);
+
+ if (!hasBody) {
+ start = end + 2;
+ }
+ } else if (name.toLowerCase().startsWith(CLOSE_TAG)) {
+ // add any contents before the tag
+ elements.add(new WOStaticElement(template.substring(index, start)));
+
// return end + name.length() + 1; // "<" + ">" - 1 = 1
- return end + (hasBody?1:2); // "<" + ">" - 1 = 1
- }
- else
- {
- // tag not interesting: continue
- start = end + (hasBody?1:2);
- }
- }
- }
-
-
- // Utility Methods
-
- static private void rewriteTag( String tagName,
- Map properties, String body, StringBuffer context )
- throws java.io.IOException
- {
- context.append( "<"+tagName );
+ return end + (hasBody ? 1 : 2); // "<" + ">" - 1 = 1
+ } else {
+ // tag not interesting: continue
+ start = end + (hasBody ? 1 : 2);
+ }
+ }
+ }
+
+ // Utility Methods
+
+ static private void rewriteTag(String tagName, Map properties, String body, StringBuffer context)
+ throws java.io.IOException {
+ context.append("<" + tagName);
Iterator it = properties.keySet().iterator();
String key;
- while ( it.hasNext() )
- {
+ while (it.hasNext()) {
key = (String) it.next();
- context.append( " " + key + "=\"" + properties.get( key ) + "\"" );
+ context.append(" " + key + "=\"" + properties.get(key) + "\"");
}
-
- if ( body == null )
- {
- context.append( "/>" );
+
+ if (body == null) {
+ context.append("/>");
return;
}
-
- context.append( ">" + body + "</" + tagName + ">" );
+
+ context.append(">" + body + "</" + tagName + ">");
+ }
+
+ private String justTheClassName() {
+ String className = getClass().getName();
+ int index = className.lastIndexOf(".");
+ if (index == -1)
+ return className;
+ return className.substring(index + 1);
+ }
+
+ private String justTheResourcePath() {
+ int last = -1;
+ char[] src = getClass().getName().toCharArray();
+ char[] dst = new char[src.length];
+ for (int i = 0; i < src.length; i++) {
+ if (src[i] == '.') {
+ dst[i] = '/';
+ last = i;
+ } else {
+ dst[i] = src[i];
+ }
+ }
+ if (last == -1)
+ return null;
+ return new String(dst, 0, last);
}
-
- private String justTheClassName()
- {
- String className = getClass().getName();
- int index = className.lastIndexOf( "." );
- if ( index == -1 ) return className;
- return className.substring( index+1 );
- }
-
- private String justTheResourcePath()
- {
- int last = -1;
- char[] src = getClass().getName().toCharArray();
- char[] dst = new char[ src.length ];
- for ( int i = 0; i < src.length; i++ )
- {
- if ( src[i] == '.' )
- {
- dst[i] = '/';
- last = i;
- }
- else
- {
- dst[i] = src[i];
- }
- }
- if ( last == -1 ) return null;
- return new String( dst, 0, last );
- }
-
- private String readTemplateResource( String name, String framework, String suffix, NSArray languages )
- {
- if ( name == null ) return null;
- name = name + DIRECTORY_SUFFIX + '/' + name + suffix;
- InputStream is = null;
- if ( isCachingEnabled() )
- {
- byte[] data = WOApplication.application().resourceManager().bytesForResourceNamed(
- name, framework, languages );
- if ( data != null )
- {
- is = new ByteArrayInputStream( data );
- }
- }
- else
- {
- is = WOApplication.application().resourceManager().inputStreamForResourceNamed(
- name, framework, languages );
- }
- if ( is == null )
- {
- System.err.println( "No resources found for: " + name );
- return null;
- }
-
- // try to autodetect encoding
- String encoding = "ISO8859_1";
- try
- {
- byte[] header = new byte[4];
- is = new PushbackInputStream( is, 4 );
- is.read( header );
- if ( header[0] < 33 || header[0] > 126 )
- {
- // if any funny characters, presume UTF-16
- encoding = "UTF-16";
- if (!( header[1] < 33 || header[1] > 126 ))
- {
- // if second character is valid, presume UTF-8
- encoding = "UTF-8";
- }
- }
- // check byte-order-mark
- if (header[0] == 0xef && header[1] == 0xbb && header[2] == 0xbf) // utf-8
- {
- encoding = "UTF-8";
- }
- else
- if (header[0] == 0xfe && header[1] == 0xff) // utf-16
- {
- encoding = "UTF-16";
- }
- else
- if (header[0] == 0 && header[1] == 0 && header[2] == 0xfe && header[3] == 0xff) // ucs-4
- {
- encoding = "UCS-4"; //??
- }
- else
- if (header[0] == 0xff && header[1] == 0xfe) // ucs-2le, ucs-4le, and
- {
- encoding = "UCS-16le"; //??
- }
- // put back the header
- ((PushbackInputStream)is).unread( header );
- }
- catch ( Throwable t )
- {
- t.printStackTrace();
- System.err.println(
- "Error while autodetecting encoding: should never happen" );
- }
-
- try
- {
- String line;
- StringBuffer buf = new StringBuffer();
- BufferedReader r = new BufferedReader( new InputStreamReader( is, encoding ) );
- while ( ( line = r.readLine() ) != null )
- {
- buf.append( line );
- buf.append( '\n' );
- }
- is.close(); // release the resource
- return buf.toString();
- }
- catch ( IOException exc )
- {
- System.err.println( "Error while reading: " + name );
- exc.printStackTrace();
- return null;
- }
- }
-
- // Declaration Parsing
-
- /**
- * Parses the declarations in the specified content and returns a map of element names
- * to maps of attribute names to WOAssociations.
- */
- private static NSDictionary processDeclaration( String content )
- {
- int index;
- NSMutableDictionary result = new NSMutableDictionary();
-
- // strip out comments
- StringBuffer stripped = new StringBuffer();
- try
- {
- LineNumberReader reader =
- new LineNumberReader( new StringReader( content ) );
- String line;
- while ( ( line = reader.readLine() ) != null )
- {
- index = line.indexOf("//");
- while (index > -1) {
- //(chochos) This used to truncate lines with quoted URLs
- //in them. We have to check that the "//" is not inside quotes.
- boolean quoted = false;
- if (index > 0) {
- for (int _position = 0; _position < index; _position++)
- if (line.charAt(_position) == '"')
- quoted = !quoted;
- }
- if (!quoted) {
- line = line.substring( 0, index );
- index = -1;
- } else {
- //if we didn't truncate the line it's because the //
- //were quoted. let's look for more, and check if they're not quoted...
- index = line.indexOf("\"", index);
- if (index > 0) {
- index = line.indexOf("//", index);
- }
- }
- }
- stripped.append( line );
- }
+
+ private String readTemplateResource(String name, String framework, String suffix, NSArray languages) {
+ if (name == null)
+ return null;
+ name = name + DIRECTORY_SUFFIX + '/' + name + suffix;
+ InputStream is = null;
+ if (isCachingEnabled()) {
+ byte[] data = WOApplication.application().resourceManager().bytesForResourceNamed(name, framework,
+ languages);
+ if (data != null) {
+ is = new ByteArrayInputStream(data);
+ }
+ } else {
+ is = WOApplication.application().resourceManager().inputStreamForResourceNamed(name, framework, languages);
}
- catch ( IOException exc )
- {
- throw new RuntimeException(
- "Error while stripping comments from declaration: " + stripped );
+ if (is == null) {
+ System.err.println("No resources found for: " + name);
+ return null;
}
- while ( (index = stripped.toString().indexOf( "/*" )) != -1 )
- {
- int j = stripped.toString().indexOf( "*/", index+1 );
- if ( j == -1 ) break;
- stripped.delete( index, j+2 );
- }
-
- String token;
- StringTokenizer tokens = new StringTokenizer( stripped.toString(), "{}", true );
- while ( tokens.hasMoreTokens() )
- {
- token = tokens.nextToken();
-
- // next token is the name and class
- String name, cl;
- index = token.indexOf( ":" );
- if ( index > -1 )
- {
- name = token.substring( 0, index ).trim();
- cl = token.substring( index+1 ).trim();
+
+ // try to autodetect encoding
+ String encoding = "ISO8859_1";
+ try {
+ byte[] header = new byte[4];
+ is = new PushbackInputStream(is, 4);
+ is.read(header);
+ if (header[0] < 33 || header[0] > 126) {
+ // if any funny characters, presume UTF-16
+ encoding = "UTF-16";
+ if (!(header[1] < 33 || header[1] > 126)) {
+ // if second character is valid, presume UTF-8
+ encoding = "UTF-8";
+ }
}
- else
+ // check byte-order-mark
+ if (header[0] == 0xef && header[1] == 0xbb && header[2] == 0xbf) // utf-8
+ {
+ encoding = "UTF-8";
+ } else if (header[0] == 0xfe && header[1] == 0xff) // utf-16
+ {
+ encoding = "UTF-16";
+ } else if (header[0] == 0 && header[1] == 0 && header[2] == 0xfe && header[3] == 0xff) // ucs-4
{
- System.err.println( "Could not parse declaration:" );
- System.err.println( content );
- throw new RuntimeException(
- "Could not parse declaration: " + token );
- }
+ encoding = "UCS-4"; // ??
+ } else if (header[0] == 0xff && header[1] == 0xfe) // ucs-2le, ucs-4le, and
+ {
+ encoding = "UCS-16le"; // ??
+ }
+ // put back the header
+ ((PushbackInputStream) is).unread(header);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.err.println("Error while autodetecting encoding: should never happen");
+ }
+
+ try {
+ String line;
+ StringBuffer buf = new StringBuffer();
+ BufferedReader r = new BufferedReader(new InputStreamReader(is, encoding));
+ while ((line = r.readLine()) != null) {
+ buf.append(line);
+ buf.append('\n');
+ }
+ is.close(); // release the resource
+ return buf.toString();
+ } catch (IOException exc) {
+ System.err.println("Error while reading: " + name);
+ exc.printStackTrace();
+ return null;
+ }
+ }
+
+ // Declaration Parsing
+
+ /**
+ * Parses the declarations in the specified content and returns a map of element
+ * names to maps of attribute names to WOAssociations.
+ */
+ private static NSDictionary processDeclaration(String content) {
+ int index;
+ NSMutableDictionary result = new NSMutableDictionary();
+
+ // strip out comments
+ StringBuffer stripped = new StringBuffer();
+ try {
+ LineNumberReader reader = new LineNumberReader(new StringReader(content));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ index = line.indexOf("//");
+ while (index > -1) {
+ // (chochos) This used to truncate lines with quoted URLs
+ // in them. We have to check that the "//" is not inside quotes.
+ boolean quoted = false;
+ if (index > 0) {
+ for (int _position = 0; _position < index; _position++)
+ if (line.charAt(_position) == '"')
+ quoted = !quoted;
+ }
+ if (!quoted) {
+ line = line.substring(0, index);
+ index = -1;
+ } else {
+ // if we didn't truncate the line it's because the //
+ // were quoted. let's look for more, and check if they're not quoted...
+ index = line.indexOf("\"", index);
+ if (index > 0) {
+ index = line.indexOf("//", index);
+ }
+ }
+ }
+ stripped.append(line);
+ }
+ } catch (IOException exc) {
+ throw new RuntimeException("Error while stripping comments from declaration: " + stripped);
+ }
+ while ((index = stripped.toString().indexOf("/*")) != -1) {
+ int j = stripped.toString().indexOf("*/", index + 1);
+ if (j == -1)
+ break;
+ stripped.delete(index, j + 2);
+ }
+
+ String token;
+ StringTokenizer tokens = new StringTokenizer(stripped.toString(), "{}", true);
+ while (tokens.hasMoreTokens()) {
+ token = tokens.nextToken();
+
+ // next token is the name and class
+ String name, cl;
+ index = token.indexOf(":");
+ if (index > -1) {
+ name = token.substring(0, index).trim();
+ cl = token.substring(index + 1).trim();
+ } else {
+ System.err.println("Could not parse declaration:");
+ System.err.println(content);
+ throw new RuntimeException("Could not parse declaration: " + token);
+ }
// next token is the declaration for the name and class
- if ( ! tokens.hasMoreTokens() )
- {
- System.err.println( "Could not find associations for declaration:" );
- System.err.println( content );
- throw new RuntimeException(
- "Could not find associations for declaration: " + name );
+ if (!tokens.hasMoreTokens()) {
+ System.err.println("Could not find associations for declaration:");
+ System.err.println(content);
+ throw new RuntimeException("Could not find associations for declaration: " + name);
+ }
+
+ token = tokens.nextToken();
+ if (token.equals("{")) {
+ if (!tokens.hasMoreTokens())
+ throw new RuntimeException("Error parsing declaration: expected { but found: '" + token + "'");
+ token = tokens.nextToken();
+ }
+
+ NSMutableDictionary associations = new NSMutableDictionary();
+
+ if (!token.equals("}")) {
+ String line, key, value;
+ StringTokenizer lines = new StringTokenizer(token, ";");
+ while (lines.hasMoreElements()) {
+ line = lines.nextToken();
+ index = line.indexOf("=");
+ if (index > -1) {
+ if (line.length() == index + 1)
+ line += " ";
+ key = line.substring(0, index).trim();
+ value = line.substring(index + 1).trim();
+ } else {
+ // not a valid key: skip
+ key = null;
+ value = null;
+ }
+
+ if (key != null) {
+ // if in quotation marks
+ if ((value.startsWith("\"")) && (value.endsWith("\""))) {
+ // it's a constant value association
+ value = value.substring(1, value.length() - 1);
+ associations.put(key, WOAssociation.associationWithValue(value));
+ } else if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
+ // HACK: needed to be compatible with woextensions
+ // apparently true and false are allowed without quotes
+ associations.put(key, WOAssociation.associationWithValue(value));
+ } else {
+ // HACK: needed to be compatible with woextensions:
+ // apparently a standalone integer is allowed without quotes.
+ try {
+ Integer.parseInt(value); // does it parse?
+ associations.put(key, WOAssociation.associationWithValue(value));
+ } catch (NumberFormatException nfe) {
+ // did not parse:
+ // it's a key path association
+ associations.put(key, WOAssociation.associationWithKeyPath(value));
+ }
+ }
+ }
+ }
+ if (tokens.hasMoreTokens()) {
+ token = tokens.nextToken();
+ if (!token.equals("}"))
+ throw new RuntimeException("Error parsing declaration: expected } but found: '" + token + "'");
+ }
}
-
- token = tokens.nextToken();
- if ( token.equals( "{" ) )
- {
- if ( !tokens.hasMoreTokens() ) throw new RuntimeException(
- "Error parsing declaration: expected { but found: '" + token + "'" );
- token = tokens.nextToken();
- }
-
- NSMutableDictionary associations = new NSMutableDictionary();
-
- if ( !token.equals( "}" ) )
- {
- String line, key, value;
- StringTokenizer lines =
- new StringTokenizer( token, ";" );
- while ( lines.hasMoreElements() )
- {
- line = lines.nextToken();
- index = line.indexOf( "=" );
- if ( index > -1 )
- {
- if ( line.length() == index+ 1 ) line += " ";
- key = line.substring( 0, index ).trim();
- value = line.substring( index+1 ).trim();
- }
- else
- {
- // not a valid key: skip
- key = null;
- value = null;
- }
-
- if ( key != null )
- {
- // if in quotation marks
- if ( ( value.startsWith( "\"" ) ) && ( value.endsWith( "\"" ) ) )
- {
- // it's a constant value association
- value = value.substring( 1, value.length()-1 );
- associations.put( key,
- WOAssociation.associationWithValue( value ) );
- }
- else
- if ( value.equalsIgnoreCase( "true" ) || value.equalsIgnoreCase( "false" ) )
- {
- //HACK: needed to be compatible with woextensions
- // apparently true and false are allowed without quotes
- associations.put( key,
- WOAssociation.associationWithValue( value ) );
- }
- else
- {
- //HACK: needed to be compatible with woextensions:
- // apparently a standalone integer is allowed without quotes.
- try
- {
- Integer.parseInt( value ); // does it parse?
- associations.put( key,
- WOAssociation.associationWithValue( value ) );
- }
- catch ( NumberFormatException nfe )
- {
- // did not parse:
- // it's a key path association
- associations.put( key,
- WOAssociation.associationWithKeyPath( value ) );
- }
- }
- }
- }
- if ( tokens.hasMoreTokens() )
- {
- token = tokens.nextToken();
- if ( !token.equals( "}" ) ) throw new RuntimeException(
- "Error parsing declaration: expected } but found: '" + token + "'" );
- }
- }
- associations.put( WOApplication.ELEMENT_CLASS, cl ); // store classname
- result.put( name, associations );
-
- }
- //System.out.println( "processDeclaration: " + result );
- return result;
- }
+ associations.put(WOApplication.ELEMENT_CLASS, cl); // store classname
+ result.put(name, associations);
+
+ }
+ // System.out.println( "processDeclaration: " + result );
+ return result;
+ }
}
/*
- * $Log$
- * Revision 1.2 2006/02/19 01:44:02 cgruber
- * Add xmlrpc files
- * Remove jclark and replace with dom4j and javax.xml.sax stuff
- * Re-work dependencies and imports so it all compiles.
+ * $Log$ Revision 1.2 2006/02/19 01:44:02 cgruber Add xmlrpc files Remove jclark
+ * and replace with dom4j and javax.xml.sax stuff Re-work dependencies and
+ * imports so it all compiles.
*
- * Revision 1.1 2006/02/16 13:22:22 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.32 2003/08/07 00:15:14 chochos
- * general cleanup (mostly removing unused imports)
+ * Revision 1.32 2003/08/07 00:15:14 chochos general cleanup (mostly removing
+ * unused imports)
*
- * Revision 1.31 2003/07/24 00:23:21 chochos
- * fixed problem with parsing wod files that have //-type comments. Quotes URL's would be truncated.
+ * Revision 1.31 2003/07/24 00:23:21 chochos fixed problem with parsing wod
+ * files that have //-type comments. Quotes URL's would be truncated.
*
- * Revision 1.30 2003/03/28 15:33:11 mpowers
- * Now using a PushBackInputStream for auto detection of content encoding.
- * No longer relying on markSupported() since jar input streams don't have it.
+ * Revision 1.30 2003/03/28 15:33:11 mpowers Now using a PushBackInputStream for
+ * auto detection of content encoding. No longer relying on markSupported()
+ * since jar input streams don't have it.
*
- * Revision 1.29 2003/03/03 16:41:52 mpowers
- * Bad characters in cvs log.
+ * Revision 1.29 2003/03/03 16:41:52 mpowers Bad characters in cvs log.
*
- * Revision 1.28 2003/03/03 16:37:35 mpowers
- * Better handling for string encodings.
- * Now trying to autodetect unicode-formatted templates and declarations.
- * Now handlings block-style comments in declarations.
+ * Revision 1.28 2003/03/03 16:37:35 mpowers Better handling for string
+ * encodings. Now trying to autodetect unicode-formatted templates and
+ * declarations. Now handlings block-style comments in declarations.
*
- * Revision 1.27 2003/01/28 19:33:51 mpowers
- * Implemented the rest of WOResourceManager.
- * Implemented support for java-style i18n.
- * Components now use the resource manager to load templates.
+ * Revision 1.27 2003/01/28 19:33:51 mpowers Implemented the rest of
+ * WOResourceManager. Implemented support for java-style i18n. Components now
+ * use the resource manager to load templates.
*
- * Revision 1.26 2003/01/24 20:13:22 mpowers
- * Now accepting immutable NSDictionary in constructor, not Map.
+ * Revision 1.26 2003/01/24 20:13:22 mpowers Now accepting immutable
+ * NSDictionary in constructor, not Map.
*
- * Revision 1.25 2003/01/21 17:53:45 mpowers
- * Now correctly reporting error for missing bindings.
+ * Revision 1.25 2003/01/21 17:53:45 mpowers Now correctly reporting error for
+ * missing bindings.
*
- * Revision 1.24 2003/01/20 17:50:11 mpowers
- * Caught a loop condition when same declaration was used twice.
+ * Revision 1.24 2003/01/20 17:50:11 mpowers Caught a loop condition when same
+ * declaration was used twice.
*
- * Revision 1.23 2003/01/19 22:33:25 mpowers
- * Fixed problems with classpath and dynamic class loading.
- * Dynamic elements now pass on ensureAwakeInContext.
+ * Revision 1.23 2003/01/19 22:33:25 mpowers Fixed problems with classpath and
+ * dynamic class loading. Dynamic elements now pass on ensureAwakeInContext.
* Parser how handles <standalone/> tags.
*
- * Revision 1.22 2003/01/17 22:55:09 mpowers
- * Straighted out the parent binding issue (I think).
- * Fixes for woextensions compatibility.
+ * Revision 1.22 2003/01/17 22:55:09 mpowers Straighted out the parent binding
+ * issue (I think). Fixes for woextensions compatibility.
*
- * Revision 1.21 2003/01/17 20:34:57 mpowers
- * Better handling for components and parents in the context's element stack.
+ * Revision 1.21 2003/01/17 20:34:57 mpowers Better handling for components and
+ * parents in the context's element stack.
*
- * Revision 1.19 2003/01/17 15:32:22 mpowers
- * Changes to better support generic elements and containers.
- * Now preserving newlines in templates.
+ * Revision 1.19 2003/01/17 15:32:22 mpowers Changes to better support generic
+ * elements and containers. Now preserving newlines in templates.
*
- * Revision 1.17 2003/01/16 22:47:30 mpowers
- * Compatibility changes to support compiling woextensions source.
- * (34 out of 56 classes compile!)
+ * Revision 1.17 2003/01/16 22:47:30 mpowers Compatibility changes to support
+ * compiling woextensions source. (34 out of 56 classes compile!)
*
- * Revision 1.15 2003/01/16 15:50:43 mpowers
- * More robust declaration parsing.
- * Subcomponents are now supported.
- * dynamicElementWithName can now return subcomponents.
+ * Revision 1.15 2003/01/16 15:50:43 mpowers More robust declaration parsing.
+ * Subcomponents are now supported. dynamicElementWithName can now return
+ * subcomponents.
*
- * Revision 1.14 2003/01/15 19:50:49 mpowers
- * Fixed issues with WOSession and Serializable.
- * Can now persist sessions between classloaders (hot swap of class impls).
+ * Revision 1.14 2003/01/15 19:50:49 mpowers Fixed issues with WOSession and
+ * Serializable. Can now persist sessions between classloaders (hot swap of
+ * class impls).
*
- * Revision 1.13 2003/01/15 14:33:48 mpowers
- * Refactoring: element id handling is now confined to WOParentElement.
- * Other elements/components should not have to do element id incrementing.
+ * Revision 1.13 2003/01/15 14:33:48 mpowers Refactoring: element id handling is
+ * now confined to WOParentElement. Other elements/components should not have to
+ * do element id incrementing.
*
- * Revision 1.12 2003/01/14 16:05:12 mpowers
- * Removed extraneous printlns.
+ * Revision 1.12 2003/01/14 16:05:12 mpowers Removed extraneous printlns.
*
- * Revision 1.11 2003/01/13 22:24:25 mpowers
- * Request-response cycle is working with session and page persistence.
+ * Revision 1.11 2003/01/13 22:24:25 mpowers Request-response cycle is working
+ * with session and page persistence.
*
- * Revision 1.10 2003/01/10 19:33:28 mpowers
- * Added contextID for the component url generation.
+ * Revision 1.10 2003/01/10 19:33:28 mpowers Added contextID for the component
+ * url generation.
*
- * Revision 1.9 2003/01/10 19:16:40 mpowers
- * Implemented support for page caching.
+ * Revision 1.9 2003/01/10 19:16:40 mpowers Implemented support for page
+ * caching.
*
- * Revision 1.8 2003/01/09 21:16:48 mpowers
- * Bringing request-response cycle more into conformance.
+ * Revision 1.8 2003/01/09 21:16:48 mpowers Bringing request-response cycle more
+ * into conformance.
*
- * Revision 1.7 2003/01/09 16:13:55 mpowers
- * Implemented WOComponentRequestHandler:
- * Bringing the request-response cycle more into conformance.
+ * Revision 1.7 2003/01/09 16:13:55 mpowers Implemented
+ * WOComponentRequestHandler: Bringing the request-response cycle more into
+ * conformance.
*
- * Revision 1.6 2002/12/20 22:56:33 mpowers
- * Reimplemented the template parsing again.
- * Nested components are now correctly parsed.
- * ElementID numbering is now working.
+ * Revision 1.6 2002/12/20 22:56:33 mpowers Reimplemented the template parsing
+ * again. Nested components are now correctly parsed. ElementID numbering is now
+ * working.
*
- * Revision 1.3 2002/12/18 14:12:38 mpowers
- * Support for differentiated request handlers.
- * Support url generation for WOContext and WORequest.
+ * Revision 1.3 2002/12/18 14:12:38 mpowers Support for differentiated request
+ * handlers. Support url generation for WOContext and WORequest.
*
- * Revision 1.2 2002/11/07 18:52:33 mpowers
- * New components courtesy of ezamudio@nasoft.com. Many thanks!
+ * Revision 1.2 2002/11/07 18:52:33 mpowers New components courtesy of
+ * ezamudio@nasoft.com. Many thanks!
*
- * Revision 1.1.1.1 2000/12/21 15:53:01 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:53:01 mpowers Contributing wotonomy.
*
- * Revision 1.2 2000/12/20 16:25:49 michael
- * Added log to all files.
+ * Revision 1.2 2000/12/20 16:25:49 michael Added log to all files.
*
*
*/
-