/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.xml;
import gw.config.BaseService;
import gw.internal.xml.ws.server.marshal.AdditionalCheckType;
import gw.internal.xml.ws.server.marshal.MarshalContext;
import gw.internal.xml.ws.server.marshal.MarshalInfo;
import gw.internal.xml.ws.server.marshal.UnmarshalContext;
import gw.internal.xml.ws.server.marshal.XmlMarshaller;
import gw.lang.parser.IParsedElement;
import gw.lang.reflect.IType;
import gw.xml.XmlElement;
import gw.xml.XmlSchemaAccess;
import java.util.Map;
import javax.xml.XMLConstants;
import java.util.Set;
/**
* This is what the marshaller does, marshal, unmarshal, valid types, create schemas</desc>
*
* @author dandrews
*/
public class Marshaller extends BaseService implements IMarshaller {
public MarshalInfo checkType(IParsedElement parsedElement, String label, IType type, Map<String, Object> seenNamespaces) {
final MarshalInfo marshalInfo = XmlMarshaller.getMarshalInfo( type, null );
if (marshalInfo == null) {
parsedElement.addParseException(ERR_CAN_NOT_MARSHAL_TYPE, type.getDisplayName(), label );
}
else {
if (marshalInfo instanceof AdditionalCheckType) {
((AdditionalCheckType)marshalInfo).checkType(this, parsedElement, label, type, seenNamespaces);
}
Map<String,Set<XmlSchemaAccess>> schemaAccesses = marshalInfo.getAllSchemas();
if (schemaAccesses != null) {
// print("checkType for ${type} schemaAccesses=${schemaAccesses}")
for (Map.Entry<String, Set<XmlSchemaAccess>> entry : schemaAccesses.entrySet()) {
String uri = entry.getKey();
if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri)) {
parsedElement.addParseWarning(WARN_SOME_WSDL2JAVA_DONT_SUPPORT_SCHEMA, label, uri);
}
else {
for ( XmlSchemaAccess xmlSchemaAccess : entry.getValue() ) {
XmlSchemaAccessImpl xmlSchemaAccessImpl = (XmlSchemaAccessImpl) xmlSchemaAccess;
if (xmlSchemaAccessImpl.getSchemaIndex().getPackageName().startsWith("wsi.local.")) {
parsedElement.addParseException(ERR_CAN_NOT_MARSHAL_TYPE, label, type.getDisplayName());
}
else {
XmlSchemaAccess found = (XmlSchemaAccess) seenNamespaces.get(uri);
if (found != null) {
if (!found.equals(xmlSchemaAccessImpl)) {
parsedElement.addParseException(ERR_DUPLICATE_NAMESPACE, label, uri, found, type.getDisplayName());
}
}
else {
seenNamespaces.put(uri, xmlSchemaAccessImpl);
}
}
}
}
}
}
}
return marshalInfo;
}
@Override
public String createTargetNamespace( String prefix, IType type ) {
return XmlMarshaller.createTargetNamespace( prefix, type);
}
@Override
public String createTargetNamespace( String prefix, String path ) {
return XmlMarshaller.createTargetNamespace( prefix, path );
}
/** This will create elements for the type in the target.
*
* @param parameterElement where to write the value
* @param type the expected type of the object (e.g., may be an interface)
* @param obj the actual object
* @param context the context for this marshalling
*/
public void marshal(XmlElement parameterElement, IType type, Object obj, MarshalContext context) {
MarshalInfo marshalInfo = XmlMarshaller.getMarshalInfo( type, null );
if ( marshalInfo == null ) {
throw new IllegalArgumentException( "Marshal/unmarshal of " + type.getName() + " is not supported" );
}
else if (!type.isValid()) {
throw new RuntimeException("Type " + type + " is not valid");
}
marshalInfo.marshal( parameterElement, type, obj, context);
}
/** This will create an object from the xml element. There are several marshalling
* attributes that will affect this behavior.
*
* @param type the type desired
* @param parameterElement the element to unmarshal
* @param context the context for this unmarshalling
* @return the create and populated object
*/
public Object unmarshal(IType type, XmlElement parameterElement, UnmarshalContext context) {
if ( parameterElement == null ) {
// null
return null;
}
else {
// not null
MarshalInfo marshalInfo = XmlMarshaller.getMarshalInfo( type, null );
if (marshalInfo == null) {
throw new RuntimeException("Could not get a marshal for " + type);
}
else if (!type.isValid()) {
throw new RuntimeException("Type " + type + " is not valid");
}
else {
return marshalInfo.unmarshal( parameterElement, context );
}
}
}
}