Details
-
Bug
-
Status: Open
-
Major
-
Resolution: Unresolved
-
Version 2
-
None
-
None
Description
The main problem here is inside InterfaceExtensionImpl when methods validateMethods() and validateMethod() are called.
The perform validation against just interface without any knowing of bean schema class which will be used for extention.
Lets imagine the situation when schema have type "tOne" and "tTwo" and "tTwo" extends "tOne"
<complexType name="tTwo">
<complexContent>
<extension base="tOne"/>
</complexContent>
</complexType>
In this case generated bean TOne will extends TTwo.
I want to create extention for TOne and TTwo. I want: TOne extends interface First, TTwo extends interface Second. But also I want to keep original
schema hierarchy , so I want also interface Second extends First.
Original implementation doesn't allow to me handle this situation : see bug http://issues.apache.org/jira/browse/XMLBEANS-205.
If this bug will be resolved then anyway I will need to create corresponding methods in SecondHandler methods that will be responsible for
delegation methods from First interface because all methods in First interface also exist in Second. BUT TTwo already extends TOne and
I don't need to create static methods for delegation them from First interface. They already exists in TTwo because it originally extends TOne. And
those methods delegated already in handler for First. But configuration file knows nothing about schema extentions and validate methiods just against
handlers and interfaces as couple. So we have the problem.
I suggest some changes in InterfaceExtensionImpl.java, SchemaTypeImpl.java, SchemaTypeSystemCompiler.java.
Possibly this is not best fix but it works and more appropriate fix wil need changes in architecture......
( I suggest that bug http://issues.apache.org/jira/browse/XMLBEANS-205 already fixed as described )
( changes marked with "!" )
changes in SchemaTypeSystemCompiler.java :
public static boolean generateTypes(SchemaTypeSystem system, Filer filer, XmlOptions options)
{
// partial type systems not allowed to be saved
if (system instanceof SchemaTypeSystemImpl && ((SchemaTypeSystemImpl)system).isIncomplete())
return false;
boolean success = true;
List types = new ArrayList();
types.addAll(Arrays.asList(system.globalTypes()));
types.addAll(Arrays.asList(system.documentTypes()));
types.addAll(Arrays.asList(system.attributeTypes()));
for (Iterator i = types.iterator(); i.hasNext(); )
{
SchemaType type = (SchemaType)i.next();
if (type.isBuiltinType())
continue;
if (type.getFullJavaName() == null)
continue;
String fjn = type.getFullJavaName();
Writer writer = null;
! // here we perform validation for interfaces that should extends
! // this type. We check whether all methods in interfaces will be
! // present or some methods will be present in supertype, in this case
! // this also Ok.
! if (!((SchemaTypeImpl)type).validateMethods() )
try
{ // Generate interface class writer = filer.createSourceFile(fjn); SchemaTypeCodePrinter.printType(writer, type, options); }catch (IOException e)
{ System.err.println("IO Error " + e); success = false; }finally {
try { if (writer != null) writer.close(); } catch (IOException e) {}
}
try
{ // Generate Implementation class fjn = type.getFullJavaImplName(); writer = filer.createSourceFile(fjn); SchemaTypeCodePrinter.printTypeImpl(writer, type, options); }
catch (IOException e)
{ System.err.println("IO Error " + e); success = false; }
finally {
try
catch (IOException e) {}
}
}
return success;
}
This block is new in SchemaTypeImpl.java :
/**
- This method should be called instead of <code>InterfaceExtension.validateMethods()</code>
- for validation interfaces for THIS type.
- The reason why <code>InterfaceExtension.validateMethods()</code> is bad :
- methods from interface can be already implemented in base type. So
- we don't need to implement them .
*/
public boolean validateMethods(){
InterfaceExtension[] extension = getInterfaceExtensions();
for (int i = 0; i < extension.length; i++)Unknown macro: { if ( !validateMethods( (InterfaceExtensionImpl)extension[i])) { return false; } }return true;
}
private boolean validateMethods(InterfaceExtensionImpl extensionImpl) {
InterfaceExtension.MethodSignature[] methods = extensionImpl.getAbsentMethods();
InterfaceExtension.MethodSignature[] inherited = getAllInheritedMethods();
for (int i = 0; i < methods.length; i++) {
InterfaceExtension.MethodSignature method = methods[i];
boolean flag = false;
for (int j = 0; j < inherited.length; j++) {
if ( extensionImpl.equals( method, inherited[j]))
}
if ( !flag )
}
return true;
}
private InterfaceExtension.MethodSignature[] getAllInheritedMethods(){
List list = new LinkedList();
SchemaType type = getBaseType();
while ( type!= null ){
if (type instanceof SchemaTypeImpl) {
SchemaTypeImpl typeImpl = (SchemaTypeImpl) type;
InterfaceExtension[] extensions = typeImpl.getInterfaceExtensions();
if (extensions != null) {
for (int i = 0; i < extensions.length; i++)
}
}
type = type.getBaseType();
}
return (InterfaceExtension.MethodSignature[])
list.toArray( new InterfaceExtension.MethodSignature[list.size()]);
}
Changes in InterfaceExtensionImpl.java :
New attributes :
private List myNotFoundMethods = new LinkedList();
private XmlObject myXMLObject ;
Inside method : static InterfaceExtensionImpl newInstance(JamClassLoader loader, NameSet xbeanSet, Extensionconfig.Interface intfXO)
result.myXMLObject = intfXO;
Changed block ( three new methods and changed old methods validateMethod() and validateMethods():
public void error( MethodSignature signature)
{ BindingConfigImpl.error("Handler class '" + _delegateToClassName + "' does not contain method " + ((MethodSignatureImpl)signature).getSignature(), myXMLObject); }/**
- This method perform "light" comparison for two methods signature
- based only on methods names and signatures. Real comperison in
- MethodSignatureImpl perform also checking for outer class name.
- @param method1
- @param method2
- @return
*/
public boolean equals( InterfaceExtension.MethodSignature method1 ,
InterfaceExtension.MethodSignature method2 ) { return ( (MethodSignatureImpl)method1).lightEqual( method2 ); }
/**
- Changed - will always return true.
- This is incorrect place for determining correctness of interface.
- Validation logic is moved into SchemaTypeImpl.validateMethods()
- @param interfaceJClass
- @param delegateJClass
- @param loc
- @return
*/
private boolean validateMethods(JClass interfaceJClass, JClass delegateJClass, XmlObject loc)
{
//assert _delegateToClass != null : "Delegate to class handler expected.";
boolean valid = true;
JMethod[] interfaceMethods = interfaceJClass.getMethods();
List list = new LinkedList();
//_methods = new MethodSignatureImpl[interfaceMethods.length];
for (int i = 0; i < interfaceMethods.length; i++)
{
JMethod method;
try {
method = validateMethod(interfaceJClass, delegateJClass, interfaceMethods[i], loc);
if (method != null)
else
{ valid = false; } }
catch (MethodNotFoundException e)
}
_methods = (MethodSignatureImpl[])list.toArray( new MethodSignatureImpl[ list.size()] );
//return valid;
return true;
}
/**
- Changed.
- Incorrect place for decision about valid method.
- Validation logic is moved into SchemaTypeImpl.validateMethods()
- @param interfaceJClass
- @param delegateJClass
- @param method
- @param loc
- @return
*/
private JMethod validateMethod(JClass interfaceJClass, JClass delegateJClass, JMethod method, XmlObject loc)
throws MethodNotFoundException {
String methodName = method.getSimpleName();
JParameter[] params = method.getParameters();
JClass returnType = method.getReturnType();
JClass[] delegateParams = new JClass[params.length+1];
delegateParams[0] = returnType.forName("org.apache.xmlbeans.XmlObject");
for (int i = 1; i < delegateParams.length; i++)
JMethod handlerMethod = null;
handlerMethod = getMethod(delegateJClass, methodName, delegateParams);
if (handlerMethod==null)
// check for throws exceptions
JClass[] intfExceptions = method.getExceptionTypes();
JClass[] delegateExceptions = handlerMethod.getExceptionTypes();
if ( delegateExceptions.length!=intfExceptions.length )
for (int i = 0; i < delegateExceptions.length; i++)
{
if ( delegateExceptions[i]!=intfExceptions[i] )
}
if (!handlerMethod.isPublic() || !handlerMethod.isStatic())
{ BindingConfigImpl.error("Method '" + delegateJClass.getQualifiedName() + "." + methodName + "(" + listTypes(delegateParams) + ")' must be declared public and static.", loc); throw new MethodNotFoundException(); //return null; }if (!returnType.equals(handlerMethod.getReturnType()))
{ BindingConfigImpl.error("Return type for method '" + handlerMethod.getReturnType() + " " + delegateJClass.getQualifiedName() + "." + methodName + "(" + listTypes(delegateParams) + ")' does not match the return type of the interface method :'" + returnType + "'.", loc); throw new MethodNotFoundException(); //return null; } return method;
}
public InterfaceExtensionImpl.MethodSignatureImpl[] getAbsentMethods()
{ return (InterfaceExtensionImpl.MethodSignatureImpl[]) myNotFoundMethods.toArray( new InterfaceExtensionImpl.MethodSignatureImpl[myNotFoundMethods.size()]); }/**
- This exception will be thrown if method was FOUND in handler
- via name and signature but it have wrong return type, exceptions that
- can be thrown , etc.
- @author ads
*
*/
private class MethodNotFoundException extends Exception{
}
I can also send all these changed java files .