Merged V2.0 to HEAD

5178: WCM-336, checkin performance
   5182: Missing OpenSearch strings
   5183: AR-1126
   5185: OpenSearch externalized strings
   5190: Schema and xforms
   5191: WCM-343
   5205: NTML using incorrect auth component
   5210: No virtual server start
   5211: WCM-352, WCM-353
   5212: Manage Task Dialog issues


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5332 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-03-07 15:04:21 +00:00
parent 52a3fa1ed1
commit 2725498515
17 changed files with 487 additions and 165 deletions

View File

@@ -135,7 +135,7 @@ public class Schema2XForms
final ResourceBundle resourceBundle)
throws FormBuilderException
{
final XSModel schema = SchemaUtil.parseSchema(schemaDocument);
final XSModel schema = SchemaUtil.parseSchema(schemaDocument, true);
this.typeTree = SchemaUtil.buildTypeTree(schema);
//refCounter = 0;
@@ -278,9 +278,13 @@ public class Schema2XForms
if (importedInstanceDocumentElement != null)
{
this.insertUpdatedNodes(importedInstanceDocumentElement,
defaultInstanceDocumentElement,
schemaNamespacesMap);
this.insertPrototypeNodes(importedInstanceDocumentElement,
defaultInstanceDocumentElement,
schemaNamespacesMap);
}
this.createSubmitElements(xformsDocument, modelSection, rootGroup);
@@ -303,6 +307,117 @@ public class Schema2XForms
this.counter.clear();
}
/**
* Inserts nodes that exist in the prototype document that are absent in the imported instance.
* This is to handle the case where a schema has been updated since the last time the
* imported document was modified.
*
* @param instanceDocumentElement the user provided instance document
* @param prototypeInstanceElement the generated prototype instance document
* @param schemaNamespaces the namespaces used by the instance document needed for
* initializing the xpath context.
*/
private void insertUpdatedNodes(final Element instanceDocumentElement,
final Element prototypeDocumentElement,
final HashMap<String, String> schemaNamespaces)
{
LOGGER.debug("updating imported instance document");
final JXPathContext prototypeContext =
JXPathContext.newContext(prototypeDocumentElement);
prototypeContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX,
NamespaceService.ALFRESCO_URI);
final JXPathContext instanceContext =
JXPathContext.newContext(instanceDocumentElement);
instanceContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX,
NamespaceService.ALFRESCO_URI);
// identify all non prototype elements in the prototypeDocument
for (final String prefix : schemaNamespaces.keySet())
{
prototypeContext.registerNamespace(prefix, schemaNamespaces.get(prefix));
instanceContext.registerNamespace(prefix, schemaNamespaces.get(prefix));
}
final Iterator it =
prototypeContext.iteratePointers("//*[not(@" + NamespaceService.ALFRESCO_PREFIX +
":prototype='true')] | //@*[name()!='" + NamespaceService.ALFRESCO_PREFIX +
":prototype']");
while (it.hasNext())
{
final Pointer p = (Pointer)it.next();
if (LOGGER.isDebugEnabled())
{
LOGGER.debug("evaluating prototype node " + p.asPath() +
" normalized " + p.asPath().replaceAll("\\[\\d+\\]", ""));
}
String path = p.asPath().replaceAll("\\[\\d+\\]", "");
if (path.lastIndexOf("/") == 0)
{
if (instanceContext.selectNodes(path).size() == 0)
{
LOGGER.debug("copying " + path + " into imported instance");
// remove child elements - we want attributes but don't want to
// copy any potential prototyp nodes
final Node clone = ((Node)p.getNode()).cloneNode(true);
if (clone instanceof Attr)
{
instanceDocumentElement.setAttributeNode((Attr)clone);
}
else
{
final NodeList children = clone.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
if (children.item(i) instanceof Element)
{
clone.removeChild(children.item(i));
}
}
instanceDocumentElement.appendChild(clone);
}
}
}
else
{
// change path /foo/bar into /foo[not(child::bar)]
if (path.indexOf("@") >= 0)
{
path = path.replaceAll("\\/(@.+)$", "[not($1)]");
}
else
{
path = path.replaceAll("\\/([^/]+)$", "[not(child::$1)]");
}
final List<Node> l = (List<Node>)instanceContext.selectNodes(path);
LOGGER.debug("appending node " + ((Node)p.getNode()).getNodeName() +
" to the " + l.size() + " selected nodes matching path " + path);
for (Node n : l)
{
// remove child elements - we want attributes but don't want to
// copy any potential prototyp nodes
final Node clone = ((Node)p.getNode()).cloneNode(true);
if (clone instanceof Attr)
{
((Element)n).setAttributeNode((Attr)clone);
}
else
{
final NodeList children = clone.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
if (children.item(i) instanceof Element)
{
clone.removeChild(children.item(i));
}
}
n.appendChild(clone);
}
}
}
}
}
/**
* Inserts prototype nodes into the provided instance document by aggregating insertion
* points from the generated prototype instance docment.

View File

@@ -32,7 +32,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xerces.xs.*;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.*;
import org.w3c.dom.Document;
import org.w3c.dom.*;
/**
* Provides utility functions for xml schema parsing.
@@ -208,7 +208,8 @@ public class SchemaUtil
return SchemaUtil.DATA_TYPE_TO_NAME.get(type);
}
public static XSModel parseSchema(final Document schemaDocument)
public static XSModel parseSchema(final Document schemaDocument,
final boolean failOnError)
throws FormBuilderException
{
try
@@ -222,13 +223,59 @@ public class SchemaUtil
final DOMImplementationLS lsImpl = (DOMImplementationLS)
registry.getDOMImplementation("XML 1.0 LS 3.0");
if (lsImpl == null)
{
throw new FormBuilderException("unable to create DOMImplementationLS using " + registry);
}
final LSInput in = lsImpl.createLSInput();
in.setStringData(XMLUtil.toString(schemaDocument));
final XSImplementation xsImpl = (XSImplementation)
registry.getDOMImplementation("XS-Loader");
final XSLoader schemaLoader = xsImpl.createXSLoader(null);
final DOMConfiguration config = schemaLoader.getConfig();
final LinkedList<DOMError> errors = new LinkedList<DOMError>();
config.setParameter("error-handler", new DOMErrorHandler()
{
public boolean handleError(final DOMError domError)
{
errors.add(domError);
return true;
}
});
final XSModel result = schemaLoader.load(in);
if (failOnError && errors.size() != 0)
{
final HashSet<String> messages = new HashSet<String>();
StringBuilder message = null;
for (DOMError e : errors)
{
message = new StringBuilder();
final DOMLocator dl = e.getLocation();
if (dl != null)
{
message.append("at line ").append(dl.getLineNumber())
.append(" column ").append(dl.getColumnNumber());
if (dl.getRelatedNode() != null)
{
message.append(" node ").append(dl.getRelatedNode().getNodeName());
}
message.append(": ").append(e.getMessage());
}
messages.add(message.toString());
}
message = new StringBuilder();
message.append(messages.size() > 1 ? "errors" : "error").append(" parsing schema: \n");
for (final String s : messages)
{
message.append(s).append("\n");
}
throw new FormBuilderException(message.toString());
}
if (result == null)
{
throw new FormBuilderException("invalid schema");