hlship 2004/05/07 14:37:41
Modified: framework/src/java/org/apache/hivemind/ant
ConstructRegistry.java
library project.xml
framework/src/test/hivemind/test/ant
TestConstructRegistry.java
framework project.xml
src/xsl hivemind.xsl
Added: framework/src/test/hivemind/test/ant
TestSDLDocumentAdaptor.java Sample.sdl
framework/src/test-data/TestConstructRegistry master.sdl
Symbols.sdl testSDL.xml
framework/src/java/org/apache/hivemind/sdl
SDLDocumentAdaptor.java
Log:
Fix ConstructRegistry Ant task to read SDL and XML files propertly (bare, or
within JARs).
Update the HiveDoc stylesheet to produce SDL syntax.
Revision Changes Path
1.4 +115 -35
jakarta-hivemind/framework/src/java/org/apache/hivemind/ant/ConstructRegistry.java
Index: ConstructRegistry.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/ant/ConstructRegistry.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ConstructRegistry.java 28 Apr 2004 23:31:17 -0000 1.3
+++ ConstructRegistry.java 7 May 2004 21:37:40 -0000 1.4
@@ -14,20 +14,25 @@
package org.apache.hivemind.ant;
+import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import org.apache.hivemind.Resource;
import org.apache.hivemind.impl.RegistryBuilder;
+import org.apache.hivemind.sdl.*;
+import org.apache.hivemind.util.URLResource;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
@@ -37,7 +42,9 @@
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
/**
* Reads some number of hivemodule deployment descriptors (specified as a
fileset)
@@ -69,6 +76,12 @@
private File _output;
private Path _descriptorsPath;
+ /**
+ * List of [EMAIL PROTECTED] org.apache.hivemind.Resource} of additional
+ * descriptors to parse.
+ */
+ private List _resourceQueue = new ArrayList();
+
public void execute() throws BuildException
{
if (_output == null)
@@ -128,24 +141,13 @@
result.appendChild(registry);
- for (int i = 0; i < moduleDescriptors.length; i++)
- {
- File f = moduleDescriptors[i];
-
- log("Reading " + f);
-
- Document module = parse(builder, f);
-
- if (module == null)
- continue;
-
- Element e = module.getDocumentElement();
-
- Node eCopy = result.importNode(e, true);
+ enqueue(moduleDescriptors);
- prepareModuleForInclusion((Element) eCopy);
+ while (!_resourceQueue.isEmpty())
+ {
+ Resource r = (Resource) _resourceQueue.remove(0);
- registry.appendChild(eCopy);
+ processResource(r, builder, registry);
}
return result;
@@ -156,40 +158,116 @@
}
}
- private Document parse(DocumentBuilder builder, File file) throws
SAXException, IOException
+ private void enqueue(File[] descriptors) throws IOException
+ {
+ for (int i = 0; i < descriptors.length; i++)
+ enqueue(descriptors[i]);
+ }
+
+ /**
+ * Queues up a single descriptor which may be a raw XML or SDL
+ * file, or a JAR (containing XML or SDL files).
+ */
+ private void enqueue(File file) throws IOException
{
if (file.getName().endsWith(".jar"))
- return parseFromJAR(builder, file);
+ {
+ enqueueJar(file);
+ return;
+ }
- log("Reading deployment descriptor from " + file);
+ URL fileURL = file.toURL();
+ Resource r = new URLResource(fileURL);
- return builder.parse(file);
+ enqueue(r);
}
- private Document parseFromJAR(DocumentBuilder builder, File file)
+ private void enqueue(Resource resource)
+ {
+ _resourceQueue.add(resource);
+ }
+
+ private void enqueueJar(File jarFile) throws IOException
+ {
+ URL jarRootURL = new URL("jar:" + jarFile.toURL() + "!/");
+
+ Resource jarResource = new URLResource(jarRootURL);
+
+ enqueueIfExists(jarResource, RegistryBuilder.HIVE_MODULE_SDL);
+ enqueueIfExists(jarResource, RegistryBuilder.HIVE_MODULE_XML);
+ }
+
+ private void enqueueIfExists(Resource jarResource, String path)
+ {
+ Resource r = jarResource.getRelativeResource(path);
+
+ if (r.getResourceURL() != null)
+ enqueue(r);
+ }
+ private void processResource(
+ Resource descriptor,
+ DocumentBuilder builder,
+ Element registryElement)
throws SAXException, IOException
{
- JarFile jar = new JarFile(file);
+ log("Reading " + descriptor);
- ZipEntry entry = jar.getEntry(RegistryBuilder.HIVE_MODULE_XML);
+ Document module = parse(builder, descriptor);
- if (entry == null)
- {
- log(file + " does not contain a HiveMind deployment descriptor");
- return null;
- }
+ Element e = module.getDocumentElement();
+
+ prepareModuleForInclusion(e);
- log("Reading deployment descriptor for " + file);
+ Document d = (Document) registryElement.getParentNode();
- InputStream stream = jar.getInputStream(entry);
+ Node eCopy = d.importNode(e, true);
- Document result = builder.parse(stream);
+ registryElement.appendChild(eCopy);
+
+ }
+
+ private Document parse(DocumentBuilder builder, Resource descriptor)
+ throws SAXException, IOException
+ {
+ String path = descriptor.getPath();
- stream.close();
+ if (path.endsWith(".sdl"))
+ return parseSDL(builder, descriptor);
+
+ return parseXML(builder, descriptor);
+ }
+
+ private Document parseSDL(DocumentBuilder builder, Resource descriptor)
+ throws SAXParseException, IOException
+ {
+ Document result = builder.newDocument();
+ SDLDocumentAdaptor parser = new SDLDocumentAdaptor(result);
+
+ parser.parse(descriptor);
return result;
}
+ private Document parseXML(DocumentBuilder builder, Resource descriptor)
+ throws SAXException, IOException
+ {
+ URL resourceURL = descriptor.getResourceURL();
+
+ InputStream rawStream = resourceURL.openStream();
+ InputStream stream = new BufferedInputStream(rawStream);
+
+ InputSource source = new InputSource(stream);
+
+ try
+ {
+ return builder.parse(source);
+ }
+ finally
+ {
+ stream.close();
+ }
+ }
+
private void writeDocument(Document document, File file) throws
BuildException
{
try
@@ -255,6 +333,8 @@
if (name.equals("service-point") ||
name.equals("implementation"))
qualifyServiceIds(moduleId, e);
+
+ // TODO: submodule!
}
1.8 +2 -2 jakarta-hivemind/library/project.xml
Index: project.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/library/project.xml,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- project.xml 28 Apr 2004 23:31:16 -0000 1.7
+++ project.xml 7 May 2004 21:37:40 -0000 1.8
@@ -25,7 +25,7 @@
<organization>
<name>Apache Software Foundation</name>
<url>http://jakarta.apache.org/</url>
- <logo>/../images/jakarta-logo-blue.png</logo>
+ <logo>/../images/jakarta-log.gif</logo>
</organization>
<inceptionYear>2003</inceptionYear>
<package>org.apache.hivemind</package>
1.6 +25 -1
jakarta-hivemind/framework/src/test/hivemind/test/ant/TestConstructRegistry.java
Index: TestConstructRegistry.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/test/hivemind/test/ant/TestConstructRegistry.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- TestConstructRegistry.java 26 Feb 2004 23:08:02 -0000 1.5
+++ TestConstructRegistry.java 7 May 2004 21:37:40 -0000 1.6
@@ -118,6 +118,30 @@
compare(output,
getFrameworkPath("src/test-data/TestConstructRegistry/testBasic.xml"));
}
+ public void testSDL() throws Exception
+ {
+ ConstructRegistry cr = create();
+
+ Path p = cr.createDescriptors();
+
+ p.createPath().setLocation(
+ new
File(getFrameworkPath("src/test-data/TestConstructRegistry/master.sdl")));
+ p.createPath().setLocation(
+ new
File(getFrameworkPath("src/test-data/TestConstructRegistry/Symbols.sdl")));
+
+ File output = File.createTempFile("testSDL-", ".xml");
+
+ // Delete the file, to force the task to re-create it.
+
+ output.delete();
+
+ cr.setOutput(output);
+
+ cr.execute();
+
+ compare(output,
getFrameworkPath("src/test-data/TestConstructRegistry/testSDL.xml"));
+ }
+
public void testLocalRefs() throws Exception
{
ConstructRegistry cr = create();
1.1
jakarta-hivemind/framework/src/test/hivemind/test/ant/TestSDLDocumentAdaptor.java
Index: TestSDLDocumentAdaptor.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 hivemind.test.ant;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.hivemind.Resource;
import org.apache.hivemind.sdl.SDLDocumentAdaptor;
import org.apache.hivemind.test.HiveMindTestCase;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.helpers.AttributesImpl;
/**
* Tests for the [EMAIL PROTECTED]
org.apache.hivemind.ant.ParseSDLIntoDocument} class.
*
* @author Howard Lewis Ship
* @version $Id: TestSDLDocumentAdaptor.java,v 1.1 2004/05/07 21:37:40 hlship
Exp $
*/
public class TestSDLDocumentAdaptor extends HiveMindTestCase
{
public void testMinimalDocument() throws Exception
{
Document d = createDocument();
SDLDocumentAdaptor adaptor = new SDLDocumentAdaptor(d);
AttributesImpl a = new AttributesImpl();
adaptor.startElement(null, "module", null, a);
adaptor.endElement(null, "module", null);
Element e = d.getDocumentElement();
assertEquals("module", e.getTagName());
}
public void testNodeContent() throws Exception
{
Document d = createDocument();
SDLDocumentAdaptor adaptor = new SDLDocumentAdaptor(d);
AttributesImpl a = new AttributesImpl();
adaptor.startElement(null, "module", null, a);
adaptor.characters("text".toCharArray(), 0, 4);
a = new AttributesImpl();
adaptor.startElement(null, "fred", null, a);
adaptor.endElement(null, "fred", null);
adaptor.endElement(null, "module", null);
Element e = d.getDocumentElement();
assertEquals("module", e.getTagName());
CDATASection cd = (CDATASection) e.getFirstChild();
assertEquals("text", cd.getData());
Element fred = (Element) cd.getNextSibling();
assertEquals("fred", fred.getTagName());
}
public void testAttributes() throws Exception
{
Document d = createDocument();
SDLDocumentAdaptor adaptor = new SDLDocumentAdaptor(d);
AttributesImpl a = new AttributesImpl();
a.addAttribute(null, "id", null, "CDATA", "foo.bar.baz");
adaptor.startElement(null, "module", null, a);
adaptor.endElement(null, "module", null);
Element e = d.getDocumentElement();
assertEquals("module", e.getTagName());
assertEquals("foo.bar.baz", e.getAttribute("id"));
assertEquals(1, e.getAttributes().getLength());
}
public void testParse() throws Exception
{
Document d = createDocument();
SDLDocumentAdaptor adaptor = new SDLDocumentAdaptor(d);
Resource r = getResource("Sample.sdl");
adaptor.parse(r);
Element e = d.getDocumentElement();
assertEquals("module", e.getTagName());
assertEquals("hivemind", e.getAttribute("id"));
assertEquals("1.0.0", e.getAttribute("version"));
assertEquals(2, e.getAttributes().getLength());
}
private Document createDocument() throws Exception
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.newDocument();
}
}
1.1
jakarta-hivemind/framework/src/test/hivemind/test/ant/Sample.sdl
Index: Sample.sdl
===================================================================
// 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.
// $Id: Sample.sdl,v 1.1 2004/05/07 21:37:40 hlship Exp $
module (id=hivemind version="1.0.0")
{
}
1.16 +2 -2 jakarta-hivemind/framework/project.xml
Index: project.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/framework/project.xml,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- project.xml 28 Apr 2004 23:31:16 -0000 1.15
+++ project.xml 7 May 2004 21:37:40 -0000 1.16
@@ -25,7 +25,7 @@
<organization>
<name>Apache Software Foundation</name>
<url>http://jakarta.apache.org/</url>
- <logo>/../images/jakarta-logo-blue.png</logo>
+ <logo>/../images/jakarta-log.gif</logo>
</organization>
<inceptionYear>2003</inceptionYear>
<package>org.apache.hivemind</package>
1.1
jakarta-hivemind/framework/src/test-data/TestConstructRegistry/master.sdl
Index: master.sdl
===================================================================
// 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.
// $Id: master.sdl,v 1.1 2004/05/07 21:37:40 hlship Exp $
module (id=hivemind version="1.0.0")
{
description { "The master module for HiveMind, defining core, universal
functionality." }
configuration-point (id=SymbolSource)
{
description { "Provides a list of sources for vlaues of
substitution symbols." }
schema
{
element (name=source)
{
description { "Describes a single source of
symbol values." }
attribute (name=order)
{
description { "A number used to set the
order in which sources are checked." }
}
attribute (name=class)
{
description { "Name of a class
implementing the SymbolSource interface." }
}
attribute (name=service-id)
{
description { "Service configuration id
for a service which implements the SymbolSource interface." }
}
conversion
(class=org.apache.hivemind.SymbolSourceContribution)
{
map (attribute=class property=source
translator=object)
map (attribute=service-id
property=source translator=service)
}
}
}
}
contribution (configuration-id=SymbolSource)
{
source (order= 900000
service-id=ApplicationDefaultsSymbolSource)
source (order=1000000 service-id=FactoryDefaultsSymbolSource)
}
configuration-point (id=FactoryDefaults)
{
description { <<Extension point for setting "factory defaults"
for symbol values.>> }
schema (id=defaults)
{
element (name=default)
{
description { "Provides a default symbol
value." }
attribute (name=symbol required=true)
{
description { "The id of the symbol to
define a default value for." }
}
attribute (name=value required=true)
{
description { "The value for the
symbol." }
}
conversion
(class=org.apache.hivemind.service.impl.FactoryDefault)
}
}
}
configuration-point (id=ApplicationDefaults)
{
description
{
"Extension point for setting application defaults;
these defaults will override "
"factory defaults specified in the FactoryDefaults
configuration point."
}
schema (ref-id=defaults)
}
service-point (id=FactoryDefaultsSymbolSource
interface=org.apache.hivemind.SymbolSource)
{
description { "SymbolSource implementation driven by the
FactoryDefaults configuration point." }
invoke-factory (service-id=BuilderFactory)
{
construct
(class=org.apache.hivemind.service.impl.DefaultsSymbolSource log-property=log)
{
set-configuration (configuration-id=FactoryDefaults
property=defaults)
}
}
}
service-point (id=ApplicationDefaultsSymbolSource
interface=org.apache.hivemind.SymbolSource)
{
description { "SymbolSource implementation driven by the
ApplicationDefaults configuration point." }
invoke-factory (service-id=BuilderFactory)
{
construct
(class=org.apache.hivemind.service.impl.DefaultsSymbolSource log-property=log)
{
set-configuration
(configuration-id=ApplicationDefaults property=defaults)
}
}
}
service-point (id=ClassFactory
interface=org.apache.hivemind.service.ClassFactory)
{
description { "Wrapper around Javassist used to dynamically
create classes such as service interceptors." }
create-instance
(class=org.apache.hivemind.service.impl.ClassFactoryImpl model=primitive)
}
service-point (id=LoggingInterceptor
interface=org.apache.hivemind.ServiceInterceptorFactory)
{
description
{
"An interceptor factory for adding method-level logging
to a service. "
"Logging occurs at level DEBUG and uses the service id
as the logger. "
"Method entry (with parameters) and method exit (with
return value) are logged, "
"as are any exceptions."
}
invoke-factory (service-id=BuilderFactory model=primitive)
{
construct
(class=org.apache.hivemind.service.impl.LoggingInterceptorFactory
service-id-property=serviceId)
{
set-service (property=factory
service-id=ClassFactory)
}
}
}
// This is about as complicated as a service should probably ever get!
service-point (id=BuilderFactory
interface=org.apache.hivemind.ServiceImplementationFactory)
{
description { "Used to construct a service from a class name
and optional constructor parameters and properties." }
parameters-schema
{
element (name=construct)
{
description { "A single construct element
identifies the class to instantiate." }
attribute (name=class required=true)
{
description { "The name of the class to
instantiate." }
}
attribute (name=messages-property)
{
description { "The name of a property
to assign to invoking module's messages to." }
}
attribute (name=log-property)
{
description
{
"The name of a property to
assign the Log instance for the service to. "
"The Log instance is built from
the service configuration point id."
}
}
attribute (name=service-id-property)
{
description { "The name of a property
to assign the configuration point id of the service to." }
}
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderParameter)
read-attribute (property=className
attribute=class)
invoke-parent (method=addElement)
create-object
(class=org.apache.hivemind.service.impl.BuilderMessagesFacet)
read-attribute
(attribute=messages-property property=propertyName)
invoke-parent (method=addProperty
depth=1)
create-object
(class=org.apache.hivemind.service.impl.BuilderLogFacet)
read-attribute (attribute=log-property
property=propertyName)
invoke-parent (method=addProperty
depth=2)
create-object
(class=org.apache.hivemind.service.impl.BuilderServiceIdFacet)
read-attribute
(attribute=service-id-property property=propertyName)
invoke-parent (method=addProperty
depth=3)
}
element (name=string)
{
description { "A string value
constructor parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-content (property=value)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=int)
{
description { "An integer value
constructor parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-content (property=value
translator=int)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=long)
{
description { "A long (64-bit) integer
value constructor parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-content (property=value
translator=long)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=boolean)
{
description { "A boolean value
constructor parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-content (property=value
translator="enumeration,java.lang.Boolean,true=TRUE,false=FALSE")
invoke-parent
(method=addParameter depth=4)
}
}
element (name=service)
{
description { "A constructor parameter
providing the identified HiveMind service." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-content (property=value
translator=service)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=configuration)
{
description { "A constructor parameter
providing a HiveMind configuration point (as a List)." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-content (property=value
translator=configuration)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=resource)
{
description { "A Resource constructor
parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-content (property=value
translator=resource)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=log)
{
description { "Placeholder for a Log
instance for the constructed service as constructor parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderLogFacet)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=messages)
{
description { "Placeholder for a
Messages object (from the invoking module) as constructor parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderMessagesFacet)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=service-id)
{
description { "Placeholder for the
service id (of the constructed service) as constructor parameter." }
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderServiceIdFacet)
invoke-parent
(method=addParameter depth=4)
}
}
element (name=set)
{
description { "Configures a property of
the service instance." }
attribute (name=property required=true)
{
description { "The name of a
property of the service instance to configure." }
}
attribute (name=value required=true)
{
description
{
"The value to set the
property to. The value will be converted to the "
"type of the property."
}
}
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderSmartPropertyFacet)
read-attribute
(property=propertyName attribute=property)
read-attribute
(property=attributeValue attribute=value)
invoke-parent
(method=addProperty depth=4)
}
}
element (name=set-service)
{
description { "Configures a property of
the service instance to another service." }
attribute (name=property required=true)
{
description { "The name of the
property of the service instance to configure." }
}
attribute (name=service-id
required=true)
{
description { "The id of the
service." }
}
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-attribute
(property=propertyName attribute=property)
read-attribute (property=value
attribute=service-id translator=service)
invoke-parent
(method=addProperty depth=4)
}
}
element (name=set-configuration)
{
description
{
"Configures a property of the
service instance to the elements "
"contributed to an
configuration point."
}
attribute (name=property required=true)
{
description { "The name of the
property of the service instance to configure." }
}
attribute (name=configuration-id
required=true)
{
description { "The id of the
configuration point to access." }
}
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-attribute
(property=propertyName attribute=property)
read-attribute (property=value
attribute=configuration-id translator=configuration)
invoke-parent
(method=addProperty depth=4)
}
}
element (name=set-resource)
{
description { "Configures a property of
the service instance to a resource." }
attribute (name=property required=true)
{
description { "The name of the
property of the service instance to configure." }
}
attribute (name=path required=true)
{
description { "The path,
relative to the module's deployment descriptor, of the resource." }
}
rules
{
create-object
(class=org.apache.hivemind.service.impl.BuilderPropertyFacet)
read-attribute
(property=propertyName attribute=property)
read-attribute (property=value
attribute=path translator=resource)
invoke-parent
(method=addProperty depth=4)
}
}
element (name=event-listener)
{
description
{
"Registers the new services as
an event listener for events produced by "
"the specified service."
}
attribute (name=service-id
required=true)
{
description { "The service
which will produce events." }
}
attribute (name=event-set)
{
description
{
"If given, the name of
an event set for which the service will be registered. "
"If omitted, the
service will be registered for all events sets for which it "
"implements the
necessary listener interfaces."
}
}
rules
{
create-object
(class=org.apache.hivemind.service.impl.EventRegistration)
read-attribute
(property=producer attribute=service-id translator=service)
read-attribute
(property=eventSetName attribute=event-set)
invoke-parent
(method=addEventRegistration depth=4)
}
}
} // element construct
} // parameters-schema
create-instance
(class=org.apache.hivemind.service.impl.BuilderFactory model=primitive)
}
service-point (id=ThreadEventNotifier
interface=org.apache.hivemind.service.ThreadEventNotifier)
{
description
{
"Service used by other services to be alerted when a
thread is cleaned up (typically, at "
"the end of a request or transaction)."
}
create-instance
(class=org.apache.hivemind.service.impl.ThreadEventNotifierImpl)
}
service-point (id=ThreadLocalStorage
interface=org.apache.hivemind.service.ThreadLocalStorage)
{
description
{
"Service which manages a thread-local map of data
items. This can be used "
"for temporary storage of information when local
variables can't be used. "
"All stored items are released when the thread is
cleaned up."
}
invoke-factory (service-id=BuilderFactory)
{
construct
(class=org.apache.hivemind.service.impl.ThreadLocalStorageImpl)
{
set-service (property=notifier
service-id=ThreadEventNotifier)
}
}
}
}
1.1
jakarta-hivemind/framework/src/test-data/TestConstructRegistry/Symbols.sdl
Index: Symbols.sdl
===================================================================
// 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.
// $Id: Symbols.sdl,v 1.1 2004/05/07 21:37:40 hlship Exp $
module (id=hivemind.test.config version="1.0.0")
{
configuration-point (id=Symbols)
{
schema
{
element (name=datum)
{
attribute (name=key required=true)
attribute (name=value required=true)
conversion (class=hivemind.test.config.impl.Datum)
}
}
}
contribution (configuration-id=Symbols)
{
datum (key=wife value=${wife})
datum (key=husband value=${husband})
datum (key=work value=${work})
}
}
1.1
jakarta-hivemind/framework/src/test-data/TestConstructRegistry/testSDL.xml
Index: testSDL.xml
===================================================================
<?xml version="1.0"?>
<registry>
<module id="hivemind" uid="1" version="1.0.0">
<description uid="2"><![CDATA[The master module for HiveMind,
defining core, universal functionality.]]></description>
<configuration-point id="hivemind.SymbolSource" uid="3">
<description><![CDATA[Provides a list of sources for vlaues of
substitution symbols.]]></description>
<schema uid="4">
<element name="source">
<description><![CDATA[Describes a single source of symbol
values.]]></description>
<attribute name="order">
<description><![CDATA[A number used to set the order
in which sources are checked.]]></description>
</attribute>
<attribute name="class">
<description><![CDATA[Name of a class implementing
the SymbolSource interface.]]></description>
</attribute>
<attribute name="service-id">
<description><![CDATA[Service configuration id for a
service which implements the SymbolSource interface.]]></description>
</attribute>
<conversion
class="org.apache.hivemind.SymbolSourceContribution">
<map attribute="class" property="source"
translator="object"/>
<map attribute="service-id" property="source"
translator="service"/>
</conversion>
</element>
</schema>
</configuration-point>
<contribution configuration-id="hivemind.SymbolSource" uid="5">
<source order="900000"
service-id="ApplicationDefaultsSymbolSource"/>
<source order="1000000" service-id="FactoryDefaultsSymbolSource"/>
</contribution>
<configuration-point id="hivemind.FactoryDefaults" uid="6">
<description><![CDATA[Extension point for setting "factory
defaults" for symbol values.]]></description>
<schema id="hivemind.defaults" uid="7">
<element name="default">
<description><![CDATA[Provides a default symbol
value.]]></description>
<attribute name="symbol" required="true">
<description><![CDATA[The id of the symbol to define
a default value for.]]></description>
</attribute>
<attribute name="value" required="true">
<description><![CDATA[The value for the
symbol.]]></description>
</attribute>
<conversion
class="org.apache.hivemind.service.impl.FactoryDefault"/>
</element>
</schema>
</configuration-point>
<configuration-point id="hivemind.ApplicationDefaults" uid="8">
<description><![CDATA[Extension point for setting application
defaults; these defaults will override factory defaults specified in the
FactoryDefaults configuration point.]]></description>
<schema ref-id="hivemind.defaults" uid="9"/>
</configuration-point>
<service-point id="hivemind.FactoryDefaultsSymbolSource"
interface="org.apache.hivemind.SymbolSource" uid="10">
<description><![CDATA[SymbolSource implementation driven by the
FactoryDefaults configuration point.]]></description>
<invoke-factory service-id="hivemind.BuilderFactory">
<construct
class="org.apache.hivemind.service.impl.DefaultsSymbolSource"
log-property="log">
<set-configuration
configuration-id="FactoryDefaults"
property="defaults"/>
</construct>
</invoke-factory>
</service-point>
<service-point id="hivemind.ApplicationDefaultsSymbolSource"
interface="org.apache.hivemind.SymbolSource" uid="11">
<description><![CDATA[SymbolSource implementation driven by the
ApplicationDefaults configuration point.]]></description>
<invoke-factory service-id="hivemind.BuilderFactory">
<construct
class="org.apache.hivemind.service.impl.DefaultsSymbolSource"
log-property="log">
<set-configuration
configuration-id="ApplicationDefaults"
property="defaults"/>
</construct>
</invoke-factory>
</service-point>
<service-point id="hivemind.ClassFactory"
interface="org.apache.hivemind.service.ClassFactory" uid="12">
<description><![CDATA[Wrapper around Javassist used to
dynamically create classes such as service interceptors.]]></description>
<create-instance
class="org.apache.hivemind.service.impl.ClassFactoryImpl"
model="primitive"/>
</service-point>
<service-point id="hivemind.LoggingInterceptor"
interface="org.apache.hivemind.ServiceInterceptorFactory"
uid="13">
<description><![CDATA[An interceptor factory for adding
method-level logging to a service. Logging occurs at level DEBUG and uses the
service id as the logger. Method entry (with parameters) and method exit (with
return value) are logged, as are any exceptions.]]></description>
<invoke-factory model="primitive"
service-id="hivemind.BuilderFactory">
<construct
class="org.apache.hivemind.service.impl.LoggingInterceptorFactory"
service-id-property="serviceId">
<set-service property="factory"
service-id="ClassFactory"/>
</construct>
</invoke-factory>
</service-point>
<service-point id="hivemind.BuilderFactory"
interface="org.apache.hivemind.ServiceImplementationFactory"
uid="14">
<description><![CDATA[Used to construct a service from a class
name and optional constructor parameters and properties.]]></description>
<parameters-schema uid="15">
<element name="construct">
<description><![CDATA[A single construct element
identifies the class to instantiate.]]></description>
<attribute name="class" required="true">
<description><![CDATA[The name of the class to
instantiate.]]></description>
</attribute>
<attribute name="messages-property">
<description><![CDATA[The name of a property to
assign to invoking module's messages to.]]></description>
</attribute>
<attribute name="log-property">
<description><![CDATA[The name of a property to
assign the Log instance for the service to. The Log instance is built from the
service configuration point id.]]></description>
</attribute>
<attribute name="service-id-property">
<description><![CDATA[The name of a property to
assign the configuration point id of the service to.]]></description>
</attribute>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderParameter"/>
<read-attribute attribute="class"
property="className"/>
<invoke-parent method="addElement"/>
<create-object
class="org.apache.hivemind.service.impl.BuilderMessagesFacet"/>
<read-attribute attribute="messages-property"
property="propertyName"/>
<invoke-parent depth="1" method="addProperty"/>
<create-object
class="org.apache.hivemind.service.impl.BuilderLogFacet"/>
<read-attribute attribute="log-property"
property="propertyName"/>
<invoke-parent depth="2" method="addProperty"/>
<create-object
class="org.apache.hivemind.service.impl.BuilderServiceIdFacet"/>
<read-attribute attribute="service-id-property"
property="propertyName"/>
<invoke-parent depth="3" method="addProperty"/>
</rules>
<element name="string">
<description><![CDATA[A string value constructor
parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-content property="value"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="int">
<description><![CDATA[An integer value constructor
parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-content property="value" translator="int"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="long">
<description><![CDATA[A long (64-bit) integer value
constructor parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-content property="value" translator="long"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="boolean">
<description><![CDATA[A boolean value constructor
parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-content property="value"
translator="enumeration,java.lang.Boolean,true=TRUE,false=FALSE"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="service">
<description><![CDATA[A constructor parameter
providing the identified HiveMind service.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-content property="value"
translator="service"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="configuration">
<description><![CDATA[A constructor parameter
providing a HiveMind configuration point (as a List).]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-content property="value"
translator="configuration"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="resource">
<description><![CDATA[A Resource constructor
parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-content property="value"
translator="resource"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="log">
<description><![CDATA[Placeholder for a Log instance
for the constructed service as constructor parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderLogFacet"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="messages">
<description><![CDATA[Placeholder for a Messages
object (from the invoking module) as constructor parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderMessagesFacet"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="service-id">
<description><![CDATA[Placeholder for the service id
(of the constructed service) as constructor parameter.]]></description>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderServiceIdFacet"/>
<invoke-parent depth="4" method="addParameter"/>
</rules>
</element>
<element name="set">
<description><![CDATA[Configures a property of the
service instance.]]></description>
<attribute name="property" required="true">
<description><![CDATA[The name of a property of
the service instance to configure.]]></description>
</attribute>
<attribute name="value" required="true">
<description><![CDATA[The value to set the
property to. The value will be converted to the type of the
property.]]></description>
</attribute>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderSmartPropertyFacet"/>
<read-attribute attribute="property"
property="propertyName"/>
<read-attribute attribute="value"
property="attributeValue"/>
<invoke-parent depth="4" method="addProperty"/>
</rules>
</element>
<element name="set-service">
<description><![CDATA[Configures a property of the
service instance to another service.]]></description>
<attribute name="property" required="true">
<description><![CDATA[The name of the property of
the service instance to configure.]]></description>
</attribute>
<attribute name="service-id" required="true">
<description><![CDATA[The id of the
service.]]></description>
</attribute>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-attribute attribute="property"
property="propertyName"/>
<read-attribute attribute="service-id"
property="value" translator="service"/>
<invoke-parent depth="4" method="addProperty"/>
</rules>
</element>
<element name="set-configuration">
<description><![CDATA[Configures a property of the
service instance to the elements contributed to an configuration
point.]]></description>
<attribute name="property" required="true">
<description><![CDATA[The name of the property of
the service instance to configure.]]></description>
</attribute>
<attribute name="configuration-id" required="true">
<description><![CDATA[The id of the configuration
point to access.]]></description>
</attribute>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-attribute attribute="property"
property="propertyName"/>
<read-attribute attribute="configuration-id"
property="value" translator="configuration"/>
<invoke-parent depth="4" method="addProperty"/>
</rules>
</element>
<element name="set-resource">
<description><![CDATA[Configures a property of the
service instance to a resource.]]></description>
<attribute name="property" required="true">
<description><![CDATA[The name of the property of
the service instance to configure.]]></description>
</attribute>
<attribute name="path" required="true">
<description><![CDATA[The path, relative to the
module's deployment descriptor, of the resource.]]></description>
</attribute>
<rules>
<create-object
class="org.apache.hivemind.service.impl.BuilderPropertyFacet"/>
<read-attribute attribute="property"
property="propertyName"/>
<read-attribute attribute="path"
property="value" translator="resource"/>
<invoke-parent depth="4" method="addProperty"/>
</rules>
</element>
<element name="event-listener">
<description><![CDATA[Registers the new services as
an event listener for events produced by the specified service.]]></description>
<attribute name="service-id" required="true">
<description><![CDATA[The service which will
produce events.]]></description>
</attribute>
<attribute name="event-set">
<description><![CDATA[If given, the name of an
event set for which the service will be registered. If omitted, the service
will be registered for all events sets for which it implements the necessary
listener interfaces.]]></description>
</attribute>
<rules>
<create-object
class="org.apache.hivemind.service.impl.EventRegistration"/>
<read-attribute attribute="service-id"
property="producer" translator="service"/>
<read-attribute attribute="event-set"
property="eventSetName"/>
<invoke-parent depth="4"
method="addEventRegistration"/>
</rules>
</element>
</element>
</parameters-schema>
<create-instance
class="org.apache.hivemind.service.impl.BuilderFactory"
model="primitive"/>
</service-point>
<service-point id="hivemind.ThreadEventNotifier"
interface="org.apache.hivemind.service.ThreadEventNotifier"
uid="16">
<description><![CDATA[Service used by other services to be
alerted when a thread is cleaned up (typically, at the end of a request or
transaction).]]></description>
<create-instance
class="org.apache.hivemind.service.impl.ThreadEventNotifierImpl"/>
</service-point>
<service-point id="hivemind.ThreadLocalStorage"
interface="org.apache.hivemind.service.ThreadLocalStorage"
uid="17">
<description><![CDATA[Service which manages a thread-local map of
data items. This can be used for temporary storage of information when local
variables can't be used. All stored items are released when the thread is
cleaned up.]]></description>
<invoke-factory service-id="hivemind.BuilderFactory">
<construct
class="org.apache.hivemind.service.impl.ThreadLocalStorageImpl">
<set-service property="notifier"
service-id="ThreadEventNotifier"/>
</construct>
</invoke-factory>
</service-point>
</module>
<module id="hivemind.test.config" uid="18" version="1.0.0">
<configuration-point id="hivemind.test.config.Symbols" uid="19">
<schema uid="20">
<element name="datum">
<attribute name="key" required="true"/>
<attribute name="value" required="true"/>
<conversion class="hivemind.test.config.impl.Datum"/>
</element>
</schema>
</configuration-point>
<contribution configuration-id="hivemind.test.config.Symbols"
uid="21">
<datum key="wife" value="${wife}"/>
<datum key="husband" value="${husband}"/>
<datum key="work" value="${work}"/>
</contribution>
</module>
</registry>
1.1
jakarta-hivemind/framework/src/java/org/apache/hivemind/sdl/SDLDocumentAdaptor.java
Index: SDLDocumentAdaptor.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.sdl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hivemind.Resource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
* An adaptor that allows the content of an SDL file (as a [EMAIL PROTECTED]
Resource}) to
* be parsed into an existing [EMAIL PROTECTED] org.w3c.dom.Document}.
*
* @author Howard Lewis Ship
* @version $Id: SDLDocumentAdaptor.java,v 1.1 2004/05/07 21:37:41 hlship Exp
$
*/
public class SDLDocumentAdaptor extends DefaultHandler
{
private Document _document;
private List _nodeStack = new ArrayList();
public SDLDocumentAdaptor(Document document)
{
_document = document;
_nodeStack.add(document);
}
public void parse(Resource resource) throws SAXParseException, IOException
{
SDLResourceParser parser = new SDLResourceParser();
parser.parseResource(resource, this);
}
private Node peek()
{
return (Node) _nodeStack.get(_nodeStack.size() - 1);
}
public void characters(char[] ch, int start, int length) throws
SAXException
{
Node currentElement = peek();
String data = new String(ch, start, length);
Node textNode = _document.createCDATASection(data);
currentElement.appendChild(textNode);
}
public void endElement(String uri, String localName, String qName) throws
SAXException
{
pop();
}
private void pop()
{
int count = _nodeStack.size();
_nodeStack.remove(count - 1);
}
public void startElement(String uri, String localName, String qName,
Attributes attributes)
throws SAXException
{
Node parentElement = peek();
// The SDL parser provides just localName, never qName
Element newElement = _document.createElement(localName);
int count = attributes.getLength();
for (int i = 0; i < count; i++)
{
String name = attributes.getLocalName(i);
String value = attributes.getValue(i);
newElement.setAttribute(name, value);
}
parentElement.appendChild(newElement);
push(newElement);
}
private void push(Node node)
{
_nodeStack.add(node);
}
}
1.26 +47 -39 jakarta-hivemind/src/xsl/hivemind.xsl
Index: hivemind.xsl
===================================================================
RCS file: /home/cvs/jakarta-hivemind/src/xsl/hivemind.xsl,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- hivemind.xsl 18 Apr 2004 17:39:58 -0000 1.25
+++ hivemind.xsl 7 May 2004 21:37:41 -0000 1.26
@@ -285,7 +285,7 @@
<xsl:template match="element">
<tr>
- <th class="section-id" colspan="3">Element <span
class="tag"><<xsl:value-of select="@name"/>></span></th>
+ <th class="section-id" colspan="3">Element <span
class="tag"><xsl:value-of select="@name"/></span></th>
</tr>
@@ -453,61 +453,63 @@
<xsl:template match="create-instance">
<li>
- <span class="tag"><create-instance</span>
- <span class="attribute"> class</span>="<xsl:value-of
select="@class"/>"
+ <span class="tag">create-instance</span> (
+ <span class="attribute"> class</span>=<xsl:value-of
select="@class"/>
<xsl:if test="@model">
- <span class="attribute">
model</span>="<xsl:value-of select="@model"/>"
- </xsl:if>
- <span class="tag">/></span>
+ <span class="attribute">
model</span>=<xsl:value-of select="@model"/>
+ </xsl:if> )
</li>
</xsl:template>
<xsl:template match="invoke-factory">
<li>
- <span class="tag"><invoke-factory</span>
- <span class="attribute">
service-id</span>="<xsl:apply-templates select="/registry/module/[EMAIL
PROTECTED] = current()/@service-id]" mode="link"/>"
+ <span class="tag">invoke-factory</span> (
+ <span class="attribute">
service-id</span>=<xsl:apply-templates select="/registry/module/[EMAIL
PROTECTED] = current()/@service-id]" mode="link"/>
<xsl:if test="@model">
- <span class="attribute">
model</span>="<xsl:value-of select="@model"/>"
+ <span class="attribute">
model</span>=<xsl:value-of select="@model"/>
</xsl:if>
- >
+ )
<xsl:if test="*">
+ <br/>
+ {
<ul>
<xsl:apply-templates mode="raw"/>
- </ul>
+ </ul>
+ }
</xsl:if>
- <span class="tag"></invoke-factory></span>
</li>
</xsl:template>
<xsl:template match="interceptor">
<li>
- <span class="tag"><interceptor</span>
- <span class="attribute">
service-id</span>="<xsl:apply-templates select="/registry/module/[EMAIL
PROTECTED] = current()/@service-id]" mode="link"/>"
+ <span class="tag">interceptor</span> (
+ <span class="attribute">
service-id</span>=<xsl:apply-templates select="/registry/module/[EMAIL
PROTECTED] = current()/@service-id]" mode="link"/>
<xsl:if test="@before">
- <span class="attribute"> before</span>="<xsl:value-of
select="@before"/>"
+ <span class="attribute"> before</span>=<xsl:value-of
select="@before"/>
</xsl:if>
<xsl:if test="@after">
- <span class="attribute"> after</span>="<xsl:value-of
select="@after"/>"
+ <span class="attribute"> after</span>=<xsl:value-of
select="@after"/>
</xsl:if>
-
+ )
<xsl:choose>
<xsl:when test="*">
- <span class="tag">></span>
+ <br/>
+ {
<ul>
<xsl:apply-templates mode="raw"/>
</ul>
- <span class="tag"></interceptor></span>
+ }
</xsl:when>
<xsl:when test="normalize-space()">
- <span class="tag">></span>
- <xsl:value-of select="."/>
- <span
class="tag"></interceptor></span>
+ <br/>
+ {
+ <ul>
+ <li><xsl:value-of select="."/></li>
+ </ul>
+ }
</xsl:when>
- <xsl:otherwise>
- <span class="tag">/></span>
- </xsl:otherwise>
</xsl:choose>
</li>
@@ -516,27 +518,33 @@
<xsl:template match="*" mode="raw">
<li>
- <span class="tag"><<xsl:value-of select="name()"/></span>
- <xsl:for-each select="@*" xml:space="preserve">
- <span class="attribute"> <xsl:value-of
select="name()"/></span>="<xsl:value-of select="."/>"
- </xsl:for-each>
+ <span class="tag"><xsl:value-of select="name()"/></span>
+ <xsl:if test="@*">
+ (
+ <xsl:for-each select="@*" xml:space="preserve">
+ <span class="attribute"> <xsl:value-of
select="name()"/></span>=<xsl:value-of select="."/>
+ </xsl:for-each>
+ )
+ </xsl:if>
+
<xsl:choose>
<xsl:when test="*">
- <span class="tag">></span>
+ <br/>
+ {
<ul>
<xsl:apply-templates mode="raw"/>
</ul>
- <span class="tag"></<xsl:value-of
select="name()"/>></span>
+ }
</xsl:when>
<xsl:when test="normalize-space()">
- <span class="tag">></span>
- <xsl:value-of select="."/>
- <span class="tag"></<xsl:value-of
select="name()"/>></span>
+ <br/>
+ {
+ <ul>
+ <li><xsl:value-of select="."/></li>
+ </ul>
+ }
</xsl:when>
- <xsl:otherwise>
- <span class="tag">/></span>
- </xsl:otherwise>
- </xsl:choose>
+ </xsl:choose>
</li>
</xsl:template>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]