/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.xml.ws.server.marshal;
import gw.internal.xml.Marshaller;
import gw.internal.xml.config.XmlServices;
import gw.internal.xml.ws.WsiAdditions;
import gw.internal.xml.ws.server.WsiServiceInfo;
import gw.lang.parser.IParsedElement;
import gw.lang.parser.resources.Res;
import gw.lang.reflect.IAnnotationInfo;
import gw.lang.reflect.IPropertyInfo;
import gw.lang.reflect.IRelativeTypeInfo;
import gw.lang.reflect.IType;
import gw.lang.reflect.ITypeInfo;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.java.JavaTypes;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import gw.util.GosuExceptionUtil;
import gw.util.concurrent.LockingLazyVar;
import gw.xml.XmlElement;
import gw.xml.XmlSchemaAccess;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import javax.xml.namespace.QName;
public class ExportableMarshalInfo extends ClassBasedMarshalInfo {
public static final LockingLazyVar<IType> _exportAnnoType = new LockingLazyVar<IType>( TypeSystem.getGlobalLock() ) {
@Override
protected IType init() {
return TypeSystem.getByFullName( "gw.xml.ws.annotation.WsiExportable" );
}
};
public ExportableMarshalInfo( IType type, boolean isComponent ) {
super( type, isComponent );
}
static boolean isExportable(IType type) {
List<IAnnotationInfo> annotation = type.getTypeInfo().getAnnotationsOfType(_exportAnnoType.get());
return annotation != null && annotation.size() > 0;
}
@Override
public void checkType(Marshaller marshaller, IParsedElement parsedElement, String label, IType type, Map<String, Object> seenNamespaces) {
if (!type.isValid() && !type.equals(_type)) {
parsedElement.addParseException(Res.WS_ERR_Can_Not_Marshal, type.getDisplayName(), label );
}
else {
for (Map.Entry<String,IPropertyInfo> prop : getProperties(type).entrySet()) {
String newLabel = label + (label.equals("") ? "" : ".") + prop.getKey();
IType partType = prop.getValue().getFeatureType();
if (!_type.equals(partType) && isExportable(partType)) {
// do not recurse
}
else if (_type.equals(getComponentType(partType))) { // test this before recursing into checkType
parsedElement.addParseWarning(Res.WS_ERR_Export_Recursive, newLabel );
}
else {
MarshalInfo marshalInfo = marshaller.checkType(parsedElement, newLabel, prop.getValue().getFeatureType(), seenNamespaces);
checkMarshalInfoType(parsedElement, prop, newLabel, marshalInfo);
}
}
}
}
private IType getComponentType(IType partType) {
if ( partType.isArray()) {
return getComponentType(partType.getComponentType());
}
if ( JavaTypes.LIST().isAssignableFrom( partType )) {
IType[] parameters = partType.getTypeParameters();
return parameters.length != 1 ? partType : getComponentType(parameters[0]);
}
return partType;
}
private void checkMarshalInfoType(IParsedElement parsedElement, Map.Entry<String, IPropertyInfo> prop, String newLabel, MarshalInfo marshalInfo) {
if (marshalInfo instanceof SimpleValueMarshalInfo) {
}
else if (marshalInfo instanceof EnumMarshalInfo) {
}
else if (marshalInfo instanceof ExportableMarshalInfo) {
}
else if (marshalInfo instanceof ArrayMarshalInfo) {
ArrayMarshalInfo ami = (ArrayMarshalInfo) marshalInfo;
MarshalInfo componentMI = ami.getComponentMarshalInfo();
checkMarshalInfoType(parsedElement, prop, newLabel + "[]", componentMI);
}
else if (marshalInfo instanceof ListMarshalInfo) {
ListMarshalInfo lmi = (ListMarshalInfo) marshalInfo;
MarshalInfo componentMI = lmi.getComponentMarshalInfo();
checkMarshalInfoType(parsedElement, prop, newLabel + "[]", componentMI);
}
else if (marshalInfo instanceof XmlElementMarshalInfo) {
// TODO when you change this you need to also deal with seen type names in getAllSchemas()
parsedElement.addParseException(Res.WS_ERR_Can_Not_Marshal, prop.getValue().getDisplayName(), newLabel );
}
else if (marshalInfo instanceof XmlTypeInstanceMarshalInfo) {
// TODO when you change this need to also deal with seen type names in getAllSchemas()
parsedElement.addParseException(Res.WS_ERR_Can_Not_Marshal, prop.getValue().getDisplayName(), newLabel );
}
else if (marshalInfo != null) {
// These other types should just be supported
parsedElement.addParseException(Res.WS_ERR_Can_Not_Marshal, prop.getValue().getDisplayName(), newLabel );
}
}
protected Map<String,IPropertyInfo> getProperties(IType type) {
Map<String, IPropertyInfo> rtn = new TreeMap<String,IPropertyInfo>();
ITypeInfo typeInfo = type.getTypeInfo();
if (typeInfo instanceof IRelativeTypeInfo) {
IRelativeTypeInfo pogoTI = ((IRelativeTypeInfo) typeInfo);
for (IPropertyInfo property : pogoTI.getDeclaredProperties()) {
if (property.isPublic() && property.isWritable() && property.isReadable()) {
rtn.put(property.getName(), property);
}
}
}
return rtn;
}
}