Issue Details (XML | Word | Printable)

Key: CASTOR-664
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Andrew Fawcett
Reporter: Heri Bender
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
castor

ExtraElement not ignored in UnmarshalHandler.startElement although it should be ignored

Created: 09/Feb/04 06:43 AM   Updated: 12/Sep/05 07:44 AM
Component/s: XML
Affects Version/s: 0.9.5.2
Fix Version/s: 0.9.9 M2

Time Tracking:
Not Specified

File Attachments: 1. Zip Archive castor.zip (2 kB)

Environment: Operating System: other
Platform: Other


 Description  « Hide
Although the unmarshaller is configured with "unm.setIgnoreExtraElements( true )" the
UnmarshalHandler does not ignore a nested unknown tag which has the same name like a known tag
within a container two level higher.

i.e.:

<root>
<container1>
<culpritTag> <--
this is known by the schema
</culpritTag>
<container2>
<culpritTag> <-- this is NOT known by
the schema and should be ignored
...
</culpritTag>
</container2>

</container1>
</root>

The bug is located in the (private)
UnmarshalHandler.startElement method.

part of this method (my comments marked with
>>>>>HB<<<<<:

...

//-- loop through stack and find correct descriptor
int pIdx =
_stateInfo.size() - 2; //-- index of parentState
UnmarshalState targetState = parentState;

String path = "";
StringBuffer pathBuf = null;
int count = 0;
boolean isWrapper = false;

XMLClassDescriptor oldClassDesc = classDesc;
while (descriptor == null) {

descriptor =
classDesc.getFieldDescriptor(name, NodeType.Element);

>>>>>HB<<<<<: within the
third loop the descriptor is no more NULL since it has found the "culpritTag" in container1

//--
Namespace patch, should be moved to XMLClassDescriptor, but
//-- this is the least intrusive
patch at the moment. kv - 20030423
if ((descriptor != null) && (!descriptor.isContainer()))
{
if ((namespace != null) && (namespace.length() > 0)) {
if (!namespaceEquals(namespace,
descriptor.getNameSpaceURI())) {
//-- if descriptor namespace is not null, then we must
//--
have a namespace match, so set descriptor to null,
//-- or if descriptor is not a wildcard we can
also
//-- set to null.
if ((descriptor.getNameSpaceURI() != null) ||
(!descriptor.matches("*"))) { descriptor = null; }

}
}
}
//-- end namespace
patch

/*
If descriptor is null, we need to handle possible inheritence,
which might
not be described in the current ClassDescriptor.
This can be a slow process...for speed use the
match attribute
of the xml element in the mapping file. This logic might
not be completely
necessary, and perhaps we should remove it.
*/
if ((descriptor == null) && (count == 0) &&
(!targetState.wrapper)) {
MarshalFramework.InheritanceMatch[] matches =
searchInheritance(name, namespace, classDesc, _cdResolver);
if (matches.length != 0) { InheritanceMatch match = matches[0]; descriptor = match.parentFieldDesc; cdInherited = match.inheritedClassDesc; break; //-- found }
isWrapper = (isWrapper ||
hasFieldsAtLocation(name, classDesc));
}
else if (descriptor != null) { >>>>>HB<<<<<: Flow is then entering here String tmpPath = descriptor.getLocationPath(); if (tmpPath == null) tmpPath = ""; if (path.equals(tmpPath)) break; //-- found >>>>>HB<<<<<: This if returns false, so no break occurs, but the variable "descriptor" is still assigned so it breaks when it tries to enter the loop again. You should put an else part where the "descriptor" is set to NULL again. }
else { if (pathBuf == null) pathBuf = new StringBuffer(); else pathBuf.setLength(0); pathBuf.append(path); pathBuf.append('/'); pathBuf.append(name); isWrapper = (isWrapper || hasFieldsAtLocation(pathBuf.toString(), classDesc)); }

//-- Make sure there are more
parent classes on stack
//-- otherwise break, since there is nothing to do
if (pIdx == 0)
break;

//-- adjust name and try parent
if (count == 0)
path = targetState.elementName;

else { if (pathBuf == null) pathBuf = new StringBuffer(); else pathBuf.setLength(0); pathBuf.append(targetState.elementName); pathBuf.append('/'); pathBuf.append(path); path = pathBuf.toString(); }

//-- get

--pIdx;
targetState = (UnmarshalState)_stateInfo.elementAt(pIdx);
classDesc =
targetState.classDesc;
count++;
}

//-- The field descriptor is still null, we face a
problem
if (descriptor == null) {
>>>>>HB<<<<<: This if is not entered since descriptor is
not NULL. But it should be entered !
//-- reset classDesc
classDesc = oldClassDesc;

//--
isWrapper?
if (isWrapper) {
state.classDesc = new
XMLClassDescriptorImpl(ContainerElement.class, name);
state.wrapper = true;
if
(debug) { message("wrapper-element: " + name); }
//-- process attributes

processWrapperAttributes(atts);
return;
}

String mesg = "unable to find
FieldDescriptor for '" + name;
mesg += "' in ClassDescriptor of " +
classDesc.getXMLName();

//-- unwrap classDesc, if necessary, for the check
//--
Introspector.introspected done below
if (classDesc instanceof
InternalXMLClassDescriptor) { classDesc = ((InternalXMLClassDescriptor)classDesc).getClassDescriptor(); }

//-- If we are
skipping elements that have appeared in the XML but for
//-- which we have no mapping, increase the
ignore depth counter and return
if (! _strictElements) {
++_ignoreElementDepth;
//--
remove the StateInfo we just added
_stateInfo.pop();
if (debug) { message(mesg + " - ignoring extra element."); }
return;
}
//if we have no field descriptor and
//the
class descriptor was introspected
//just log it
else if
(Introspector.introspected(classDesc)) { //if (warn) message(mesg); return; }

//-- otherwise report error since we cannot find a suitable
//-- descriptor
else { throw new SAXException(mesg); }
} //-- end null descriptor

...



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Keith Visco added a comment - 01/Mar/04 11:28 AM
Hi Heri, can you attach a diff -u so I can the changes easier.

Heri Bender added a comment - 01/Dec/04 05:04 AM
Dear Keith

I dont know "diff -u". My remarks within the cited code are clearly marked with
>>>>>HB<<<<< (three locations = two comments + one change proposal), so it
should be no problem for you to locate the problem.


Nikolai V. Chr. added a comment - 07/Apr/05 08:29 AM
Has this issue been solved?
Especially the part that goes like this:

//-- Namespace patch, should be moved to XMLClassDescriptor, but
//-- this is the least intrusive patch at the moment. kv - 20030423

[...]

//-- end namespace patch


Heri Bender added a comment - 13/Apr/05 01:41 AM
My bug description has nothing to do with the namespace problem.

I marked my comments and suggestions with >>>>>HB<<<<<. Isn't it obvious? I
can't believe such a simple bug fix lasts that long!


Cedric Bompart added a comment - 10/May/05 05:01 AM
This example captures this issue.

If you comment in line 58 to 60 (TestCastor class) then you should get an exception.

Here is the input XML:

<Response>
<Dob>01012005</Dob>
<User>
<Name>Cedric</Name>
<Title>M</Title>
<Dob>28011976</Dob>
</User>
</Response>

Here is a working mapping file, both "Dob" elements are not mapped.

<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<class cst:name="castor.Response">
<map-to cst:xml="Response" />
<field cst:name="user" cst:type="castor.User" cst:collection="array">
<bind-xml name="User" node="element" />
</field>
</class>

<class cst:name="castor.User">
<map-to cst:xml="User" />
<field cst:name="name" cst:type="java.lang.String">
<bind-xml name="Name" node="element" />
</field>
<field cst:name="title" cst:type="java.lang.String">
<bind-xml name="Title" node="element" />
</field>
</class>
</mapping>

If you add a mapping for the first "Dob":

<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<class cst:name="castor.Response">
<map-to cst:xml="Response" />
<field cst:name="user" cst:type="castor.User" cst:collection="array">
<bind-xml name="User" node="element" />
</field>
<field cst:name="dob" cst:type="java.lang.String">
<bind-xml name="Dob" node="element" />
</field>
</class>

<class cst:name="castor.User">
<map-to cst:xml="User" />
<field cst:name="name" cst:type="java.lang.String">
<bind-xml name="Name" node="element" />
</field>
<field cst:name="title" cst:type="java.lang.String">
<bind-xml name="Title" node="element" />
</field>
</class>
</mapping>

then you get an exception against the "User" structure for its "Dob" element.

additionally if you comment out line 40 (which is the Dob from the user structure) then you should get a working example.

So it looks like there is an "issue" with the mapping logic around duplicate elements in different structure in the same class mapping.


Andrew Fawcett added a comment - 21/May/05 10:47 AM
Applied patch sent by Heri Bender. Thanks!

Cedric Bompart added a comment - 23/May/05 07:51 AM
thanks a lot! we've going to put our application into production on the 24th of May, a bit lucky...

Werner Guttmann added a comment - 08/Sep/05 03:12 AM
Hi, as explained in CASTOR-1174, it looks like the resolution of this bug as committed by Andrew back in May unfortunately causes other code to break. As such, I am currently debating with my later ego whether to back this issue out or not. I do acknowledge that this will not please quite some folks as it will take away a solution for this very problem, but it looks like the patch in question in a bit incomplete and causes quite severe problems with more sophisticated 'locations'. Well, let's hear your views first ...

Werner Guttmann added a comment - 08/Sep/05 03:14 AM
As explained above ...

Gregory Block added a comment - 12/Sep/05 07:44 AM
Dependent bug closed; the patch remains in place. Re-closing this bug.