package org.flymine.objectstore.webservice.ser;

/*
 * Copyright (C) 2002-2003 FlyMine
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  See the LICENSE file for more
 * information or http://www.gnu.org/copyleft/lesser.html.
 *
 */

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Iterator;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;

import org.apache.log4j.Logger;

import org.flymine.objectstore.query.fql.FqlQuery;
import org.flymine.util.StringUtil;
import org.flymine.util.TypeUtil;

/**
 * Utilities used by (de)serializers
 *
 * @author Mark Woodbridge
 */
public class SerializationUtil
{
    protected static final Logger LOG = Logger.getLogger(SerializationUtil.class);

    /**
     * Return the "gettable" fields (i.e. those with a getter) of a Class (not necessarily a bean)
     *
     * @param c the class
     * @return the fields
     */
    public static Collection gettableFields(Class c) {
        Collection gettableFields = new HashSet();
        do {
            Field[] fields = c.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                try {
                    c.getDeclaredMethod("get" + StringUtil.capitalise(fields[i].getName()),
                                        new Class[0]);
                    gettableFields.add(fields[i]);
                } catch (NoSuchMethodException e) {
                }
            }
        } while ((c = c.getSuperclass()) != null);
        return gettableFields;
    }

    /**
     * Return the "gettable" fields of an Object and their corresponding values
     *
     * @param o the object
     * @return a map from Fields to values
     */
    public static Map fieldValues(Object o) {
        Iterator i = gettableFields(o.getClass()).iterator();
        Map fieldValues = new HashMap();
        while (i.hasNext()) {
            Field field = (Field) i.next();
            try {
                fieldValues.put(field, TypeUtil.getFieldValue(o, field.getName()));
            } catch (IllegalAccessException e) {
                LOG.debug(e);
            }
        }
        return fieldValues;
    }

    /**
     * Bean that represents a proxy (reference or collection), used in serialization
     */
    public static class ProxyBean
    {
        String type;
        FqlQuery fqlQuery;
        Integer id;

        /**
         * Constructor
          * @param type the type of the underlying object
          * @param fqlQuery the query to retrieve the object
          * @param id the internal id of the underlying object
          */
        public ProxyBean(String type, FqlQuery fqlQuery, Integer id) {
            this.type = type;
            this.fqlQuery = fqlQuery;
            this.id = id;
        }

        /**
         * Returns the type of the underlying object
         * @return the type
         */
        public String getType() {
            return type;
        }

        /**
         * Returns the query to retrieve the object
         * @return the query
         */
        public FqlQuery getFqlQuery() {
            return fqlQuery;
        }

        /**
         * Returns the internal id of the underlying object
         * @return the id
         */
        public Integer getId() {
            return id;
        }
    }
}

@@ -547,51 +547,80 @@
 ort 
-org.flymine.objectstore.query.fql.FqlQuery;
+javax.xml.namespace.QName;%0Aimport org.apache.axis.encoding.TypeMapping;%0A
 %0Aimp
@@ -2326,419 +2326,547 @@
   * 
-Bean that represents a proxy (reference or collection), used in serialization%0A     */%0A    public static class ProxyBean%0A    %7B%0A        String type;%0A        FqlQuery fqlQuery;%0A        Integer id;%0A%0A        /**%0A         * Constructor%0A          * @param type the type of the underlying object%0A          * @param fqlQuery the query to retrieve the object%0A          * @param id the internal id of the underlying object
+Register the default FlyMine type mappings%0A     * These should match those in the axis deployment descriptor%0A     * @param tm the type mapping to register to%0A     */%0A    public static void registerMappings(TypeMapping tm) %7B%0A        registerDefaultMapping(tm, org.flymine.objectstore.query.fql.FqlQuery.class);%0A        registerDefaultMapping(tm, org.flymine.sql.query.ExplainResult.class);%0A        registerDefaultMapping(tm, ProxyBean.class);%0A        tm.register(org.flymine.metadata.Model.class,%0A                    new QName(%22%22, %22model%22),
 %0A   
@@ -2868,35 +2868,32 @@
 ,%0A          
-*/%0A
         
 public Proxy
@@ -2884,164 +2884,139 @@
     
-public ProxyBean(String type, FqlQuery fqlQuery, Integer id) %7B%0A            this.type = type;%0A            this.fqlQuery = fqlQuery;%0A            this.id = id;
+  new ModelSerializerFactory(),%0A                    new ModelDeserializerFactory());%0A        tm.register(java.util.ArrayList.class,
 %0A   
@@ -3016,35 +3016,32 @@
 ss,%0A        
-%7D%0A%0A
         
 /**%0A        
@@ -3032,179 +3032,149 @@
     
-/**%0A         * Returns the type of the underlying object%0A         * @return the type%0A         */%0A        public String getType() %7B%0A            return type;%0A  
+    new QName(%22http://soapinterop.org/xsd%22, %22list%22),%0A                    new ListSerializerFactory(), new ListDeserializerFactory());%0A
     
-  
 %7D%0A%0A
-    
     
@@ -3186,175 +3186,341 @@
     
-    * Returns the query to retrieve the object%0A         * @return the query%0A 
+* Register type with our default (bean-like) serializer%0A     * @param tm the type mapping to register to%0A     * @param type the type to register%0A
      
-   
 */%0A    
-  
-  
 public 
-FqlQuery getFqlQuery() %7B%0A            return fqlQuery;%0A        %7D%0A
+static void registerDefaultMapping(TypeMapping tm, Class type) %7B%0A        QName qname = new QName(%22%22, TypeUtil.unqualifiedName(type.getName()));%0A        tm.register(type,
 %0A   
@@ -3520,28 +3520,24 @@
 pe,%0A        
-/**%0A
          * R
@@ -3537,162 +3537,135 @@
     
-* Returns the internal id of the underlying object%0A         * @return the id%0A         */%0A        public Integer getId() %7B%0A            return id;%0A        %7D
+   qname,%0A                    new DefaultSerializerFactory(),%0A                    new DefaultDeserializerFactory(type, qname));
 %0A   

move ProxyBean to its own class, add default type mappings