Changeset 3691 for trunk

Show
Ignore:
Timestamp:
12/03/08 17:14:06 (4 years ago)
Author:
michael
Message:

More converters support.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/build.xml

    r2863 r3691  
    1 <project name="restlet-jpa" default="help"
     1<project name="restlet-jpa" default="help" xmlns:ivy="antlib:org.apache.ivy.ant"
    22        <!-- Sarugo common ant configuration --> 
    33        <property name="ant.lib.dir" value="ant" /> 
     
    1717 
    1818        <target name="download-build.common"> 
    19                 <get src="${build.common.url}" dest="${build.common.file}" usetimestamp="true" /> 
     19                <get ignoreerrors="true" src="${build.common.url}" dest="${build.common.file}" usetimestamp="true" /> 
    2020        </target> 
    21          
    22         <import file="${build.common.file}" optional="true"/> 
    23          
     21 
     22        <import file="${build.common.file}" optional="true" /> 
     23 
    2424        <target name="bootstrap" description="Download build dependencies and libraries"> 
    2525                <mkdir dir="${ant.lib.dir}" /> 
    26                 <antcall target="download-build.common"/> 
    27                 <antcall target="common.bootstrap"/> 
     26                <antcall target="download-build.common" /> 
     27                <antcall target="common.bootstrap" /> 
     28        </target> 
     29 
     30        <target name="project.package"> 
     31                <mkdir dir="${dist.dir}" /> 
     32                <jar destfile="${dist.dir}/${project.name}-${build.rev}.jar"> 
     33                        <fileset dir="${build.dir}/main/java"> 
     34                                <include name="**/*.class" /> 
     35                                <exclude name="org/sarugo/xtc/restlet/jpa/converter/JSONConverter.class" /> 
     36                                <exclude name="org/sarugo/xtc/restlet/jpa/converter/XTCConverter.class" /> 
     37                        </fileset> 
     38                        <fileset dir="${build.dir}/main/resources" /> 
     39                </jar> 
     40                <jar destfile="${dist.dir}/${project.name}-json-${build.rev}.jar"> 
     41                        <fileset dir="${build.dir}/main/java"> 
     42                                <include name="org/sarugo/xtc/restlet/jpa/converter/JSONConverter.class" /> 
     43                        </fileset> 
     44                </jar> 
     45                <jar destfile="${dist.dir}/${project.name}-xtc-${build.rev}.jar"> 
     46                        <fileset dir="${build.dir}/main/java"> 
     47                                <include name="org/sarugo/xtc/restlet/jpa/converter/XTCConverter.class" /> 
     48                        </fileset> 
     49                </jar> 
     50                <!-- Use ivy to copy the runtime dependencies to distribution directory --> 
     51                <ivy:retrieve pattern="${dist.dir}/[artifact]-[revision].[ext]" conf="default" useOrigin="true" /> 
     52                <property name="skip.common.package" value="true" /> 
    2853        </target> 
    2954 
  • trunk/ivy.xml

    r3677 r3691  
    44  <configurations> 
    55    <conf name="default" description="Runtime configuration"/> 
     6    <conf name="json" description="JSON converter" extends="default"/> 
     7    <conf name="xtc" description="XTC converter" extends="default"/> 
    68    <conf name="compile" visibility="private" extends="default"/> 
    79    <conf name="test" visibility="private" extends="default,compile"/> 
    810  </configurations> 
     11  <publications> 
     12        <artifact name="${project.name}" conf="default" /> 
     13        <artifact name="${project.name}-json" conf="json" /> 
     14        <artifact name="${project.name}-xtc" conf="xtc" /> 
     15  </publications> 
    916  <dependencies> 
    10     <dependency org="org.restlet" name="org.restlet" rev="1.1-M2" conf="compile->default"/> 
     17    <!-- Restlet --> 
     18    <dependency org="org.restlet" name="org.restlet" rev="1.1-M2" conf="default"/> 
    1119    <dependency org="com.noelios.restlet" name="com.noelios.restlet.ext.simple" rev="1.1-M2" conf="test->default"/> 
    1220    <dependency org="com.noelios.restlet" name="com.noelios.restlet.ext.net" rev="1.1-M2" conf="test->default"/> 
    13     <dependency org="com.sdicons.jsontools" name="jsontools-core" rev="1.5" conf="default"/> 
    14     <dependency org="javax.persistence" name="persistence-api" rev="1.0" conf="compile->default"/> 
    15     <dependency org="junit" name="junit" rev="3.8.1" conf="test->default"/> 
     21    <!-- JSON --> 
     22    <dependency org="com.sdicons.jsontools" name="jsontools-core" rev="1.5" conf="json->default"/> 
     23    <!-- XTC --> 
     24    <dependency org="sarugo" name="xtc" rev="0.4.3" conf="xtc->restlet"/> 
     25    <!-- JPA --> 
     26    <dependency org="javax.persistence" name="persistence-api" rev="1.0" conf="default"/> 
    1627    <dependency org="org.hibernate" name="hibernate" rev="3.2.4.sp1" conf="test->default"/> 
    1728    <dependency org="org.hibernate" name="hibernate-entitymanager" rev="3.3.1.ga" conf="test->default"/> 
     
    1930    <dependency org="org.hibernate" name="hibernate-commons-annotations" rev="3.3.0.ga" conf="test->default"/> 
    2031    <dependency org="hsqldb" name="hsqldb" rev="1.8.0.7" conf="test->default" /> 
     32    <!-- JUnit --> 
     33    <dependency org="junit" name="junit" rev="3.8.1" conf="test->default"/> 
    2134  </dependencies> 
    2235</ivy-module> 
  • trunk/src/main/java/org/sarugo/restlet/jpa/EntityFinder.java

    r3666 r3691  
    2121import java.lang.reflect.InvocationTargetException; 
    2222import java.lang.reflect.Method; 
     23import java.util.ArrayList; 
    2324import java.util.Collections; 
     25import java.util.List; 
    2426import java.util.Map; 
    2527import java.util.logging.Level; 
     
    3335import org.restlet.data.Response; 
    3436import org.restlet.resource.Resource; 
     37import org.sarugo.restlet.jpa.converter.Converter; 
     38import org.sarugo.restlet.jpa.converter.EntityConverter; 
     39import org.sarugo.restlet.jpa.converter.EntityConverters; 
     40import org.sarugo.restlet.jpa.converter.InputConverter; 
     41import org.sarugo.restlet.jpa.converter.OutputConverter; 
    3542import org.sarugo.restlet.jpa.resource.EntityInstance; 
    3643 
     
    4956    private final Class<? extends Object> entityIdClass; 
    5057 
     58    private final List<InputConverter> inputConverters; 
     59 
     60    private final List<OutputConverter> outputConverters; 
     61 
    5162    private final Method getEntityMethod; 
    5263 
     
    6071     * Creates an entity finder. 
    6172     *  
    62      * @param router 
    63      *            The {@link EntityRouter} this finder will be be attached to. 
    64      * @param entityClass 
    65      *            The entity class this finder operates on. 
     73     * @param app 
     74     *            The {@link PersistenceApplication} this finder is associated 
     75     *            with. 
    6676     * @param resource 
    6777     *            The entity instance resource. 
    6878     */ 
    6979    @SuppressWarnings("unchecked") 
    70     public EntityFinder(EntityRouter router, Class<? extends Resource> resource) { 
    71         super(router.getContext(), resource); 
     80    public EntityFinder(PersistenceApplication app, 
     81            Class<? extends Resource> resource) { 
     82        super(app.getContext()); 
    7283        this.idAttribute = "id"; 
    7384        EntityResource erAnnotation = resource 
    7485                .getAnnotation(EntityResource.class); 
    75         this.entityClass = erAnnotation.entity(); 
     86        if (Handler.class.isAssignableFrom(resource) && erAnnotation != null) { 
     87            this.entityClass = erAnnotation.entity(); 
     88            setTargetClass((Class<? extends Handler>) resource); 
     89        } else { 
     90            throw new IllegalArgumentException( 
     91                    "Resource must be an @EntityResource or @Entity."); 
     92        } 
    7693        this.entityIdClass = EntityHelper.findIdType(entityClass); 
     94        this.inputConverters = new ArrayList<InputConverter>(); 
     95        this.outputConverters = new ArrayList<OutputConverter>(); 
     96        EntityConverters convertersAnnotation = resource 
     97                .getAnnotation(EntityConverters.class); 
     98        if (convertersAnnotation != null) { 
     99            for (EntityConverter c : convertersAnnotation.value()) { 
     100                addConverter(c, app); 
     101            } 
     102        } else { 
     103            EntityConverter c = resource.getAnnotation(EntityConverter.class); 
     104            if (c != null) { 
     105                addConverter(c, app); 
     106            } 
     107        } 
    77108        Method m = null; 
    78109        try { 
     
    96127        } 
    97128        this.getIdAttributesMethod = m; 
     129    } 
     130 
     131    private void addConverter(EntityConverter c, PersistenceApplication app) { 
     132        try { 
     133            Converter instance = c.value().getConstructor( 
     134                    PersistenceApplication.class).newInstance(app); 
     135            switch (c.type()) { 
     136            case INPUT: 
     137                inputConverters.add((InputConverter) instance); 
     138                break; 
     139 
     140            case OUTPUT: 
     141                outputConverters.add((OutputConverter) instance); 
     142                break; 
     143 
     144            case BOTH: 
     145                inputConverters.add((InputConverter) instance); 
     146                outputConverters.add((OutputConverter) instance); 
     147                break; 
     148 
     149            case UNSPECIFIED: 
     150                if (instance instanceof InputConverter) { 
     151                    inputConverters.add((InputConverter) instance); 
     152                } 
     153                if (instance instanceof OutputConverter) { 
     154                    outputConverters.add((OutputConverter) instance); 
     155                } 
     156                break; 
     157            } 
     158        } catch (RuntimeException e) { 
     159            throw e; 
     160        } catch (Exception e) { 
     161            getLogger().log(Level.WARNING, 
     162                    "Exception instantiating converter - ignoring.", e); 
     163        } 
    98164    } 
    99165 
     
    133199     * override {@link #getIdAttributes(Object)}. 
    134200     */ 
    135     public EntityFinder setIdAttribute(String idAttribute) { 
     201    public void setIdAttribute(String idAttribute) { 
    136202        this.idAttribute = idAttribute; 
    137         return this; 
    138203    } 
    139204 
     
    278343    } 
    279344 
     345    /** Used by the default {@link EntityInstance} implementation. */ 
     346    public List<InputConverter> getInputConverters() { 
     347        return inputConverters; 
     348    } 
     349 
     350    /** Used by the default {@link EntityInstance} implementation. */ 
     351    public List<OutputConverter> getOutputConverters() { 
     352        return outputConverters; 
     353    } 
     354 
    280355} 
  • trunk/src/main/java/org/sarugo/restlet/jpa/EntityRouter.java

    r3677 r3691  
    6565    } 
    6666 
     67    private final PersistenceApplication application; 
     68 
    6769    private final EntityRouter parent; 
    6870 
     
    8890    EntityRouter(PersistenceApplication application) { 
    8991        super(application.getContext()); 
     92        this.application = application; 
    9093        this.parent = null; 
    9194        this.entities = new HashMap<Class, EntityRoute>(); 
     
    9699    public EntityRouter(EntityRouter parent) { 
    97100        super(parent.getContext()); 
     101        this.application = parent.application; 
    98102        this.parent = parent; 
    99103        this.entities = new HashMap<Class, EntityRoute>(); 
     
    104108    public EntityRouter(EntityRouter parent, Class<? extends Resource> resource) { 
    105109        super(parent.getContext()); 
     110        this.application = parent.application; 
    106111        this.parent = parent; 
    107112        this.entities = new HashMap<Class, EntityRoute>(); 
     
    263268    } 
    264269 
     270    @SuppressWarnings("unchecked") 
    265271    @Override 
    266272    public Route attach(String uriPattern, Class<? extends Resource> targetClass) { 
    267273        if (targetClass.isAnnotationPresent(EntityResource.class)) { 
    268             return attach(uriPattern, new EntityFinder(this, targetClass)); 
     274            return attach(uriPattern, 
     275                    new EntityFinder(application, targetClass)); 
     276        } else if (Resource.class.isAssignableFrom(targetClass)) { 
     277            return super.attach(uriPattern, 
     278                    (Class<? extends Resource>) targetClass); 
    269279        } else { 
    270             return super.attach(uriPattern, targetClass); 
     280            throw new IllegalArgumentException( 
     281                    "Target class must be an @Entity or Resource"); 
    271282        } 
    272283    } 
     
    301312    } 
    302313 
     314    @SuppressWarnings("unchecked") 
    303315    @Override 
    304316    public final Route attachDefault( 
    305317            Class<? extends Resource> defaultTargetClass) { 
    306318        if (defaultTargetClass.isAnnotationPresent(EntityResource.class)) { 
    307             return attachDefault(new EntityFinder(this, defaultTargetClass)); 
     319            return attachDefault(new EntityFinder(application, 
     320                    defaultTargetClass)); 
     321        } else if (Resource.class.isAssignableFrom(defaultTargetClass)) { 
     322            return super 
     323                    .attachDefault((Class<? extends Resource>) defaultTargetClass); 
    308324        } else { 
    309             return super.attachDefault(defaultTargetClass); 
     325            throw new IllegalArgumentException( 
     326                    "Target class must be an @Entity or Resource"); 
    310327        } 
    311328    } 
  • trunk/src/main/java/org/sarugo/restlet/jpa/converter/Converter.java

    r3677 r3691  
    44import java.beans.PropertyEditorManager; 
    55import java.lang.reflect.Constructor; 
    6 import java.text.ParseException; 
    76 
    8 import org.restlet.data.MediaType; 
    9 import org.restlet.resource.Representation; 
    107import org.sarugo.restlet.jpa.PersistenceApplication; 
    118 
     
    2118        return application; 
    2219    } 
    23      
    24     public abstract MediaType getMediaType(); 
    25  
    26     public abstract boolean updateEntity(Object entity, 
    27             Representation representation) throws ParseException; 
    28  
    29     public abstract Representation represent(Object entity); 
    3020 
    3121    protected <T extends Object> T convertToTypeOrEntity(Class<T> type, 
  • trunk/src/main/java/org/sarugo/restlet/jpa/converter/FormConverter.java

    r3677 r3691  
    1313import org.restlet.data.MediaType; 
    1414import org.restlet.resource.Representation; 
     15import org.restlet.resource.Resource; 
    1516import org.sarugo.restlet.jpa.PersistenceApplication; 
     17import org.sarugo.restlet.jpa.resource.EntityInstance; 
    1618 
    17 public class FormEntityUpdateConverter extends Converter { 
     19public class FormConverter extends Converter implements InputConverter, 
     20        OutputConverter { 
    1821 
    19     public FormEntityUpdateConverter(PersistenceApplication application) { 
     22    public FormConverter(PersistenceApplication application) { 
    2023        super(application); 
    2124    } 
    22      
    23     @Override 
     25 
    2426    public MediaType getMediaType() { 
    2527        return MediaType.APPLICATION_WWW_FORM; 
    2628    } 
    2729 
    28     @Override 
    29     public boolean updateEntity(Object entity, Representation representation) 
     30    public boolean updateEntity(Object entity, Resource resource) 
    3031            throws ParseException { 
    31         if (!MediaType.APPLICATION_WWW_FORM.equals(representation 
    32                 .getMediaType())) { 
     32        if (!getMediaType().equals( 
     33                resource.getRequest().getEntity().getMediaType(), true)) { 
    3334            return false; 
    3435        } 
    35         Form data = new Form(representation); 
     36        Form data = resource.getRequest().getEntityAsForm(); 
    3637        try { 
    3738            for (PropertyDescriptor p : Introspector.getBeanInfo( 
     
    7172    } 
    7273 
    73     @Override 
    74     public Representation represent(Object entity) { 
     74    private Representation represent(Object entity) { 
    7575        Form form = new Form(); 
    7676        try { 
     
    9292    } 
    9393 
     94    public Representation represent(Resource resource) { 
     95        Representation representation = null; 
     96        if (resource instanceof EntityInstance) { 
     97            representation = represent(((EntityInstance) resource).getEntity()); 
     98        } 
     99        return representation; 
     100    } 
     101 
    94102} 
  • trunk/src/main/java/org/sarugo/restlet/jpa/converter/JSONConverter.java

    r3677 r3691  
    2121import java.beans.PropertyDescriptor; 
    2222import java.lang.reflect.InvocationTargetException; 
    23 import java.text.ParseException; 
    2423import java.util.HashMap; 
    2524import java.util.Map; 
     
    2827import org.restlet.data.MediaType; 
    2928import org.restlet.resource.Representation; 
     29import org.restlet.resource.Resource; 
    3030import org.restlet.resource.StringRepresentation; 
    3131import org.sarugo.restlet.jpa.PersistenceApplication; 
     32import org.sarugo.restlet.jpa.resource.EntityInstance; 
    3233 
    3334import com.sdicons.json.mapper.JSONMapper; 
    3435import com.sdicons.json.mapper.MapperException; 
    3536 
    36 public class JSONConverter extends Converter
     37public class JSONConverter extends Converter implements OutputConverter
    3738 
    38        public JSONConverter(PersistenceApplication application) { 
     39    public JSONConverter(PersistenceApplication application) { 
    3940        super(application); 
    4041    } 
    4142 
    42     @Override 
    43         public MediaType getMediaType() { 
    44                 return MediaType.APPLICATION_JSON; 
    45         } 
    46  
    47     @Override 
    48     public boolean updateEntity(Object entity, Representation representation) throws ParseException { 
    49         // TODO Auto-generated method stub 
    50         return false; 
     43    public MediaType getMediaType() { 
     44        return MediaType.APPLICATION_JSON; 
    5145    } 
    5246 
    53         @Override 
    54         public Representation represent(Object entity) { 
    55                         try { 
    56                                 // Read each property from the entity and store in a map. 
    57                                 // For properties which point to other entities, convert 
    58                                 // to a URL and store that instead of the object. 
    59                                 Map<String, Object> entityValues = new HashMap<String, Object>(); 
    60                                 for (PropertyDescriptor p : Introspector.getBeanInfo( 
    61                                                 entity.getClass()).getPropertyDescriptors()) { 
    62                                         if (p.getWriteMethod() != null && p.getReadMethod() != null) { 
    63                                                 Object value = p.getReadMethod().invoke( 
    64                                                                 entity); 
    65                         // Convert "known" entities to URLs 
    66                         String url = getApplication().getEntityURL(value); 
    67                                                 if (url != null) { 
    68                                                         value = url; 
    69                                                 } 
    70                                                 entityValues.put(p.getName(), value); 
    71                                         } 
    72                                 } 
    73                                 return new StringRepresentation(JSONMapper.toJSON(entityValues) 
    74                                                 .render(true), getMediaType()); 
    75                         } catch (MapperException e) { 
    76                                 getApplication().getLogger().log(Level.WARNING, 
    77                                                 "Unable to map entity to JSON", e); 
    78                         } catch (IntrospectionException e) { 
    79                                 getApplication().getLogger().log(Level.WARNING, 
    80                                                 "Unable to map entity to JSON", e); 
    81                         } catch (IllegalArgumentException e) { 
    82                                 getApplication().getLogger().log(Level.WARNING, 
    83                                                 "Unable to map entity to JSON", e); 
    84                         } catch (IllegalAccessException e) { 
    85                                 getApplication().getLogger().log(Level.WARNING, 
    86                                                 "Unable to map entity to JSON", e); 
    87                         } catch (InvocationTargetException e) { 
    88                                 getApplication().getLogger().log(Level.WARNING, 
    89                                                 "Unable to map entity to JSON", e); 
    90                         } 
    91                 return null; 
    92         } 
     47    private Representation represent(Object entity) { 
     48        try { 
     49            // Read each property from the entity and store in a map. 
     50            // For properties which point to other entities, convert 
     51            // to a URL and store that instead of the object. 
     52            Map<String, Object> entityValues = new HashMap<String, Object>(); 
     53            for (PropertyDescriptor p : Introspector.getBeanInfo( 
     54                    entity.getClass()).getPropertyDescriptors()) { 
     55                if (p.getWriteMethod() != null && p.getReadMethod() != null) { 
     56                    Object value = p.getReadMethod().invoke(entity); 
     57                    // Convert "known" entities to URLs 
     58                    String url = getApplication().getEntityURL(value); 
     59                    if (url != null) { 
     60                        value = url; 
     61                    } 
     62                    entityValues.put(p.getName(), value); 
     63                } 
     64            } 
     65            return new StringRepresentation(JSONMapper.toJSON(entityValues) 
     66                    .render(true), getMediaType()); 
     67        } catch (MapperException e) { 
     68            getApplication().getLogger().log(Level.WARNING, 
     69                    "Unable to map entity to JSON", e); 
     70        } catch (IntrospectionException e) { 
     71            getApplication().getLogger().log(Level.WARNING, 
     72                    "Unable to map entity to JSON", e); 
     73        } catch (IllegalArgumentException e) { 
     74            getApplication().getLogger().log(Level.WARNING, 
     75                    "Unable to map entity to JSON", e); 
     76        } catch (IllegalAccessException e) { 
     77            getApplication().getLogger().log(Level.WARNING, 
     78                    "Unable to map entity to JSON", e); 
     79        } catch (InvocationTargetException e) { 
     80            getApplication().getLogger().log(Level.WARNING, 
     81                    "Unable to map entity to JSON", e); 
     82        } 
     83        return null; 
     84    } 
     85 
     86    public Representation represent(Resource resource) { 
     87        Representation representation = null; 
     88        if (resource instanceof EntityInstance) { 
     89            representation = represent(((EntityInstance) resource).getEntity()); 
     90        } 
     91        return representation; 
     92    } 
    9393 
    9494} 
  • trunk/src/main/java/org/sarugo/restlet/jpa/converter/StringConverter.java

    r3677 r3691  
    1717package org.sarugo.restlet.jpa.converter; 
    1818 
    19 import java.text.ParseException; 
    20  
    2119import org.restlet.data.MediaType; 
    2220import org.restlet.resource.Representation; 
     21import org.restlet.resource.Resource; 
    2322import org.restlet.resource.StringRepresentation; 
    2423import org.sarugo.restlet.jpa.PersistenceApplication; 
     24import org.sarugo.restlet.jpa.resource.EntityInstance; 
    2525 
    26 public class StringEntityConverter extends Converter { 
     26public class StringConverter extends Converter implements OutputConverter { 
    2727 
    28     public StringEntityConverter(PersistenceApplication application) { 
     28    public StringConverter(PersistenceApplication application) { 
    2929        super(application); 
    3030    } 
    3131 
    32     @Override 
    3332    public MediaType getMediaType() { 
    3433        return MediaType.TEXT_PLAIN; 
    3534    } 
    3635 
    37     @Override 
    38     public Representation represent(Object entity) { 
     36    private Representation represent(Object entity) { 
    3937        return new StringRepresentation(String.valueOf(entity)); 
    4038    } 
    4139 
    42     @Override 
    43     public boolean updateEntity(Object entity, Representation representation) 
    44             throws ParseException { 
    45         // TODO Auto-generated method stub 
    46         return false; 
     40    public Representation represent(Resource resource) { 
     41        Representation representation = null; 
     42        if (resource instanceof EntityInstance) { 
     43            representation = represent(((EntityInstance) resource).getEntity()); 
     44        } 
     45        return representation; 
    4746    } 
    4847 
  • trunk/src/main/java/org/sarugo/restlet/jpa/resource/EntityInstance.java

    r3677 r3691  
    1717package org.sarugo.restlet.jpa.resource; 
    1818 
     19import java.text.ParseException; 
     20import java.util.ArrayList; 
     21import java.util.List; 
    1922import java.util.Map; 
    2023 
     
    2427import org.restlet.data.Request; 
    2528import org.restlet.data.Response; 
     29import org.restlet.data.Status; 
     30import org.restlet.resource.Representation; 
    2631import org.restlet.resource.Resource; 
     32import org.restlet.resource.ResourceException; 
     33import org.restlet.resource.Variant; 
    2734import org.sarugo.restlet.jpa.EntityFinder; 
    28 import org.sarugo.restlet.jpa.EntityRouter; 
    2935import org.sarugo.restlet.jpa.PersistenceApplication; 
    3036import org.sarugo.restlet.jpa.converter.Converter; 
     37import org.sarugo.restlet.jpa.converter.InputConverter; 
     38import org.sarugo.restlet.jpa.converter.OutputConverter; 
    3139 
    3240/** 
     
    4149    private final EntityFinder finder; 
    4250 
     51    private final List<InputConverter> inputConverters; 
     52 
     53    private final List<OutputConverter> outputConverters; 
     54 
    4355    public EntityInstance(EntityFinder finder) { 
    4456        this.finder = finder; 
     57        if (finder != null) { 
     58            this.inputConverters = new ArrayList<InputConverter>(finder 
     59                    .getInputConverters()); 
     60            this.outputConverters = new ArrayList<OutputConverter>(finder 
     61                    .getOutputConverters()); 
     62        } else { 
     63            this.inputConverters = new ArrayList<InputConverter>(); 
     64            this.outputConverters = new ArrayList<OutputConverter>(); 
     65        } 
    4566    } 
    4667 
     
    5172     */ 
    5273    @SuppressWarnings("unchecked") 
    53     public final void init(Context context, Request request, Response response) { 
     74    public void init(Context context, Request request, Response response) { 
    5475        super.init(context, request, response); 
    55         initEntity(request, response); 
     76        initEntity(); 
     77        initConverters(); 
     78        for (OutputConverter c : getOutputConverters()) { 
     79            getVariants().add(new Variant(c.getMediaType())); 
     80        } 
    5681    } 
    5782 
     
    6893     */ 
    6994    @SuppressWarnings("unchecked") 
    70     protected void initEntity(Request request, Response response) { 
    71         Object id = getId(request.getAttributes()); 
    72         if (id != null) { 
     95    protected void initEntity() { 
     96        Object id = getId(getRequest().getAttributes()); 
     97        if (id != null && finder != null) { 
    7398            entity = (E) getEntityManager().find(finder.getEntityClass(), id); 
    7499        } 
     100    } 
     101 
     102    protected void initConverters() { 
    75103    } 
    76104 
     
    93121    protected Object getId(Map<String, Object> attributes) { 
    94122        Object id = null; 
    95         String value = (String) attributes.get(finder.getIdAttribute()); 
    96         if (value != null) { 
    97             id = Converter.convertToType(finder.getEntityIdClass(), value); 
     123        if (finder != null) { 
     124            String value = (String) attributes.get(finder.getIdAttribute()); 
     125            if (value != null) { 
     126                id = Converter.convertToType(finder.getEntityIdClass(), value); 
     127            } 
    98128        } 
    99129        return id; 
     
    101131 
    102132    /** The {@link PersistenceApplication}. */ 
    103     public final PersistenceApplication getApplication() { 
     133    public PersistenceApplication getApplication() { 
    104134        return (PersistenceApplication) super.getApplication(); 
    105     } 
    106  
    107     /** The root {@link EntityRouter} that created this resource. */ 
    108     protected final EntityRouter getRouter() { 
    109         return getApplication().getEntityRouter(); 
    110135    } 
    111136 
     
    119144     * {@link #getApplication()}. 
    120145     */ 
    121     public final EntityManager getEntityManager() { 
     146    protected EntityManager getEntityManager() { 
    122147        return getApplication().getEntityManager(); 
     148    } 
     149 
     150    protected final List<InputConverter> getInputConverters() { 
     151        return inputConverters; 
     152    } 
     153 
     154    protected final List<OutputConverter> getOutputConverters() { 
     155        return outputConverters; 
    123156    } 
    124157 
     
    134167    } 
    135168 
     169    @Override 
     170    public boolean isModifiable() { 
     171        return !getInputConverters().isEmpty(); 
     172    } 
     173 
     174    @Override 
     175    public boolean allowPost() { 
     176        return false; 
     177    } 
     178 
     179    @Override 
     180    public Representation represent(Variant variant) throws ResourceException { 
     181        Representation representation = null; 
     182        for (OutputConverter c : getOutputConverters()) { 
     183            if (variant.getMediaType().equals(c.getMediaType(), true)) { 
     184                representation = c.represent(this); 
     185                if (representation != null) { 
     186                    break; 
     187                } 
     188            } 
     189        } 
     190        return representation; 
     191    } 
     192 
     193    @Override 
     194    public void storeRepresentation(Representation representation) 
     195            throws ResourceException { 
     196        if (!isAvailable()) { 
     197            throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND); 
     198        } 
     199        boolean stored = false; 
     200        for (InputConverter c : getInputConverters()) { 
     201            try { 
     202                stored = c.updateEntity(getEntity(), this); 
     203            } catch (ParseException e) { 
     204                throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, e); 
     205            } 
     206            if (stored) { 
     207                break; 
     208            } 
     209        } 
     210        // TODO commit? 
     211        if (!stored) { 
     212            throw new ResourceException( 
     213                    Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE); 
     214        } 
     215    } 
     216 
     217    @Override 
     218    public void removeRepresentations() throws ResourceException { 
     219        if (!isAvailable()) { 
     220            throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND); 
     221        } 
     222        getEntityManager().remove(getEntity()); 
     223        getEntityManager().flush(); 
     224        // TODO commit? 
     225    } 
     226 
    136227} 
  • trunk/src/main/java/org/sarugo/restlet/jpa/resource/EntityList.java

    r3666 r3691  
    11package org.sarugo.restlet.jpa.resource; 
    22 
     3import java.text.ParseException; 
    34import java.util.ArrayList; 
    45import java.util.List; 
     
    1213import org.restlet.data.Request; 
    1314import org.restlet.data.Response; 
     15import org.restlet.data.Status; 
     16import org.restlet.resource.Representation; 
    1417import org.restlet.resource.Resource; 
    15 import org.sarugo.restlet.jpa.EntityRouter; 
     18import org.restlet.resource.ResourceException; 
     19import org.restlet.resource.Variant; 
    1620import org.sarugo.restlet.jpa.PersistenceApplication; 
    17  
    18 public class EntityList<E> extends Resource { 
    19  
    20     private String queryName; 
    21  
    22     private int start = 1; 
    23  
    24     private int maxResults = 30; 
    25  
    26     private boolean hasMore = false; 
    27  
    28     private List<E> list; 
    29  
    30     private String searchString; 
     21import org.sarugo.restlet.jpa.converter.InputConverter; 
     22import org.sarugo.restlet.jpa.converter.OutputConverter; 
     23 
     24public abstract class EntityList<E> extends Resource { 
     25 
     26    private final List<InputConverter> inputConverters; 
     27 
     28    private final List<OutputConverter> outputConverters; 
     29 
     30    protected String queryName; 
     31 
     32    protected int start = 1; 
     33 
     34    protected int maxResults = 30; 
     35 
     36    protected boolean hasMore = false; 
     37 
     38    protected List<E> list; 
     39 
     40    protected String searchString; 
     41 
     42    public EntityList() { 
     43        this.inputConverters = new ArrayList<InputConverter>(); 
     44        this.outputConverters = new ArrayList<OutputConverter>(); 
     45    } 
    3146 
    3247    public void init(Context context, Request request, Response response) { 
    3348        super.init(context, request, response); 
    34         initList(); 
    35     } 
    36  
    37     @SuppressWarnings("unchecked") 
    38     protected void initList() { 
    3949        Form params = getRequest().getResourceRef().getQueryAsForm(); 
    4050        queryName = params.getFirstValue("query"); 
     
    4757            } 
    4858        } 
     59        initList(); 
     60        initConverters(); 
     61        for (OutputConverter c : getOutputConverters()) { 
     62            getVariants().add(new Variant(c.getMediaType())); 
     63        } 
     64    } 
     65 
     66    @SuppressWarnings("unchecked") 
     67    protected void initList() { 
    4968        Query q = getJPAQuery(); 
    5069        if (searchString != null && searchString.length() > 0) { 
     
    6281            list = list.subList(0, maxResults); 
    6382        } 
     83    } 
     84 
     85    protected void initConverters() { 
    6486    } 
    6587 
     
    7698    } 
    7799 
     100    protected E createEntity() { 
     101        return null; 
     102    } 
     103 
    78104    /** The {@link PersistenceApplication}. */ 
    79     public final PersistenceApplication getApplication() { 
    80         return (PersistenceApplication) getApplication(); 
    81     } 
    82  
    83     /** The root {@link EntityRouter} that created this resource. */ 
    84     protected final EntityRouter getRouter() { 
    85         return getApplication().getEntityRouter(); 
     105    public PersistenceApplication getApplication() { 
     106        return (PersistenceApplication) super.getApplication(); 
    86107    } 
    87108 
     
    90111     * {@link #getApplication()}. 
    91112     */ 
    92     public final EntityManager getEntityManager() { 
     113    protected EntityManager getEntityManager() { 
    93114        return getApplication().getEntityManager(); 
     115    } 
     116 
     117    protected List<InputConverter> getInputConverters() { 
     118        return inputConverters; 
     119    } 
     120 
     121    protected List<OutputConverter> getOutputConverters() { 
     122        return outputConverters; 
    94123    } 
    95124 
     
    126155    } 
    127156 
     157    @Override 
     158    public boolean allowPost() { 
     159        return !getInputConverters().isEmpty(); 
     160    } 
     161 
     162    @Override 
     163    public Representation represent(Variant variant) throws ResourceException { 
     164        Representation representation = null; 
     165        for (OutputConverter c : getOutputConverters()) { 
     166            if (variant.getMediaType().equals(c.getMediaType(), true)) { 
     167                representation = c.represent(this); 
     168                if (representation != null) { 
     169                    break; 
     170                } 
     171            } 
     172        } 
     173        return representation; 
     174    } 
     175 
     176    @Override 
     177    public void acceptRepresentation(Representation representation) 
     178            throws ResourceException { 
     179        if (!isAvailable()) { 
     180            throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND); 
     181        } 
     182        boolean stored = false; 
     183        E entity = createEntity(); 
     184        if (entity == null) { 
     185            throw new ResourceException(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); 
     186        } 
     187        for (InputConverter c : getInputConverters()) { 
     188            try { 
     189                stored = c.updateEntity(entity, this); 
     190            } catch (ParseException e) { 
     191                throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, e); 
     192            } 
     193            if (stored) { 
     194                break; 
     195            } 
     196        } 
     197        if (!stored) { 
     198            throw new ResourceException( 
     199                    Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE); 
     200        } else { 
     201            getEntityManager().persist(entity); 
     202            getEntityManager().flush(); 
     203            // TODO commit? 
     204            getResponse().setLocationRef(getApplication().getEntityURL(entity)); 
     205            getResponse().setStatus(Status.SUCCESS_CREATED); 
     206        } 
     207    } 
     208 
    128209}