001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/enterprise/control/RPCFactory.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.enterprise.control;
045    
046    import java.io.Reader;
047    import java.util.Date;
048    
049    import org.deegree.framework.log.ILogger;
050    import org.deegree.framework.log.LoggerFactory;
051    import org.deegree.framework.util.TimeTools;
052    import org.deegree.framework.xml.ElementList;
053    import org.deegree.framework.xml.NamespaceContext;
054    import org.deegree.framework.xml.XMLTools;
055    import org.deegree.ogcbase.CommonNamespaces;
056    import org.w3c.dom.Document;
057    import org.w3c.dom.Element;
058    
059    /**
060     * Factory class for creating RPC methodCall and methodResponse objects from their XML
061     * representation
062     * 
063     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
064     * @version $Revision: 9338 $ $Date: 2007-12-27 13:31:31 +0100 (Do, 27 Dez 2007) $
065     */
066    public class RPCFactory {
067        
068        private static final ILogger LOG = LoggerFactory.getLogger( RPCFactory.class );
069    
070        private static NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
071    
072        /**
073         * creates an instance of <tt>RPCMethodCall</tt> from an XML document that can be accessed
074         * through the passed <tt>Reader</tt>
075         * 
076         * @param reader
077         *            reader to access an XML document
078         * @return an RPCMethodCall
079         */
080        public static RPCMethodCall createRPCMethodCall( Reader reader ) throws RPCException {
081            
082            Document doc = null;
083            try {
084                doc = XMLTools.parse( reader );
085            } catch (Exception e) {
086                LOG.logError( e.getMessage(), e );
087                throw new RPCException( e.toString() );
088            }
089    
090            return createRPCMethodCall( doc );
091        }
092    
093        /**
094         * creates an instance of <tt>RPCMethodCall</tt> from the XML document passed
095         * 
096         * @param doc
097         *            XML document containing a RPC method call
098         * @return an RPCMethodCall
099         */
100        public static RPCMethodCall createRPCMethodCall( Document doc ) throws RPCException {
101         
102            RPCMethodCall mc = null;
103            try {
104                Element root = doc.getDocumentElement();
105                // get methode name - mandatory
106                String methodName = XMLTools.getRequiredStringValue( "methodName", null, root );
107    
108                Element params = XMLTools.getChildElement( "params", null, root );
109    
110                RPCParameter[] parameters = null;
111                if ( params != null ) {
112                    ElementList el = XMLTools.getChildElements( params );
113                    if ( el != null ) {
114                        parameters = new RPCParameter[el.getLength()];
115                        for (int i = 0; i < el.getLength(); i++) {
116                            parameters[i] = createRPCParam( el.item( i ) );
117                        }
118                    }
119                } else {
120                    parameters = new RPCParameter[0];
121                }
122    
123                mc = new RPCMethodCall( methodName, parameters );
124            } catch (Exception e) {
125                LOG.logError( e.getMessage(), e );
126                throw new RPCException( e.toString() );
127            }
128    
129            return mc;
130        }
131    
132        /**
133         * creates an instance of <tt>RPCMethodResponse</tt> from an XML document that can be accessed
134         * through the passed <tt>Reader</tt>
135         * 
136         * @param reader
137         *            reader to access an XML document
138         * @return created <tt>RPCMethodResponse</tt>
139         */
140        public static RPCMethodResponse createRPCMethodResponse( Reader reader ) throws RPCException {
141         
142            Document doc = null;
143            try {
144                doc = XMLTools.parse( reader );
145            } catch (Exception e) {
146                LOG.logError( e.getMessage(), e );
147                throw new RPCException( e.toString() );
148            }
149    
150            return createRPCMethodResponse( doc );
151        }
152    
153        /**
154         * creates an instance of <tt>RPCMethodResponse</tt> from the XML document passed
155         * 
156         * @param doc
157         *            XML document containing a RPC method call
158         * @return created <tt>RPCMethodResponse</tt>
159         */
160        public static RPCMethodResponse createRPCMethodResponse( Document doc ) throws RPCException {
161            
162            RPCMethodResponse mc = null;
163            try {
164                Element root = doc.getDocumentElement();
165    
166                Element params = XMLTools.getChildElement( "params", null, root );
167    
168                if ( params != null ) {
169                    ElementList el = XMLTools.getChildElements( params );
170                    RPCParameter[] parameters = null;
171                    if ( el != null ) {
172                        parameters = new RPCParameter[el.getLength()];
173                        for (int i = 0; i < el.getLength(); i++) {
174                            parameters[i] = createRPCParam( el.item( i ) );
175                        }
176                    }
177                    mc = new RPCMethodResponse( parameters );
178                } else {
179                    // a fault is contained instead of the expected result
180                    Element fault = XMLTools.getChildElement( "fault", null, root );
181                    RPCFault rpcFault = createRPCFault( fault );
182                    mc = new RPCMethodResponse( rpcFault );
183                }
184    
185            } catch (Exception e) {
186                LOG.logError( e.getMessage(), e );
187                throw new RPCException( e.toString() );
188            }
189    
190            return mc;
191        }
192    
193        /**
194         * @param par
195         * @return
196         * @throws RPCException
197         */
198        public static RPCMethodResponse createRPCMethodResponse( RPCParameter[] par ) {
199            RPCMethodResponse mc = null;
200            if ( par != null ) {
201                RPCParameter[] params = par;
202                mc = new RPCMethodResponse( params );
203            } else {
204                LOG.logError( "Fehler createRPCMEthodResponse in RPSFactory" );
205            }
206            return mc;
207        }
208    
209        /**
210         * creates a <tt>RPCParameter</tt> from its XML representation
211         * 
212         * @param param
213         *            element containing a RPC param
214         * @return created <tt>RPCParameter</tt>
215         */
216        private static RPCParameter createRPCParam( Element param ) throws RPCException {
217            
218            RPCParameter parameter = null;
219            try {
220                Element value = XMLTools.getChildElement( "value", null, param );
221                Element child = XMLTools.getFirstChildElement( value );
222                Object o = null;
223                Class cl = null;
224                if ( child.getNodeName().equals( "struct" ) ) {
225                    o = createRPCStruct( child );
226                    cl = RPCStruct.class;
227                } else if ( child.getNodeName().equals( "string" ) ) {
228                    o = XMLTools.getRequiredStringValue( "string", null, value );
229                    cl = String.class;
230                } else if ( child.getNodeName().equals( "int" ) ) {
231                    double d = XMLTools.getRequiredNodeAsDouble( value, "./int", nsContext );
232                    o = new Integer( (int) d );
233                    cl = Integer.class;
234                } else if ( child.getNodeName().equals( "i4" ) ) {
235                    double d = XMLTools.getRequiredNodeAsDouble( value, "./i4", nsContext );
236                    o = new Integer( (int) d );
237                    cl = Integer.class;
238                } else if ( child.getNodeName().equals( "double" ) ) {
239                    double d = XMLTools.getRequiredNodeAsDouble( value, "./double", nsContext );
240                    o = new Double( d );
241                    cl = Double.class;
242                } else if ( child.getNodeName().equals( "boolean" ) ) {
243                    o = Boolean.valueOf( child.getFirstChild().getNodeValue().equals( "1" ) );
244                    cl = Boolean.class;
245                } else if ( child.getNodeName().equals( "dateTime.iso8601" ) ) {
246                    String s = XMLTools.getRequiredStringValue( "dateTime.iso8601", null, value );
247                    o = TimeTools.createCalendar( s ).getTime();
248                    cl = Date.class;
249                } else if ( child.getNodeName().equals( "base64" ) ) {
250                } else if ( child.getNodeName().equals( "array" ) ) {
251                    o = createArray( child );
252                    cl = RPCParameter[].class;
253                }
254                parameter = new RPCParameter( cl, o );
255            } catch (Exception e) {
256                LOG.logError( e.getMessage(), e );
257                throw new RPCException( e.toString() );
258            }
259    
260            return parameter;
261        }
262    
263        /**
264         * creates a RPC struture object from the passed <tt>Element</tt>
265         * 
266         * @param struct
267         *            element containing a RPC struct
268         * @return created <tt>RPCStruct</tt>
269         */
270        private static RPCStruct createRPCStruct( Element struct ) throws RPCException {
271    
272            RPCStruct structure = null;
273            try {
274                ElementList el = XMLTools.getChildElements( struct );
275                RPCMember[] members = null;
276                if ( el != null ) {
277                    members = new RPCMember[el.getLength()];
278                    for (int i = 0; i < el.getLength(); i++) {
279                        members[i] = createRPCMember( el.item( i ) );
280                    }
281                }
282                structure = new RPCStruct( members );
283            } catch (Exception e) {
284                LOG.logError( e.getMessage(), e );
285                throw new RPCException( e.toString() );
286            }
287    
288            return structure;
289        }
290    
291        /**
292         * creates a RPC struture member object from the passed <tt>Element</tt>
293         * 
294         * @param member
295         *            element containing a RPC member
296         * @return created <tt>RPCMember</tt>
297         */
298        private static RPCMember createRPCMember( Element member ) throws RPCException {
299    
300            RPCMember mem = null;        
301            try {
302                String name = XMLTools.getRequiredStringValue( "name", null, member );
303                Element value = XMLTools.getChildElement( "value", null, member );
304                Element child = XMLTools.getFirstChildElement( value );
305                Object o = null;
306                Class cl = null;
307                if ( child.getNodeName().equals( "struct" ) ) {
308                    o = createRPCStruct( child );
309                    cl = RPCStruct.class;
310                } else if ( child.getNodeName().equals( "string" ) ) {
311                    o = XMLTools.getRequiredStringValue( "string", null, value );
312                    cl = String.class;
313                } else if ( child.getNodeName().equals( "int" ) ) {
314                    double d = XMLTools.getRequiredNodeAsDouble( value, "./int", nsContext );
315                    o = new Integer( (int) d );
316                    cl = Integer.class;
317                } else if ( child.getNodeName().equals( "i4" ) ) {
318                    double d = XMLTools.getRequiredNodeAsDouble( value, "./i4", nsContext );
319                    o = new Integer( (int) d );
320                    cl = Integer.class;
321                } else if ( child.getNodeName().equals( "double" ) ) {
322                    double d = XMLTools.getRequiredNodeAsDouble( value, "./double", nsContext );
323                    o = new Double( d );
324                    cl = Double.class;
325                } else if ( child.getNodeName().equals( "boolean" ) ) {
326                    o = Boolean.valueOf( child.getFirstChild().getNodeValue().equals( "1" ) );
327                    cl = Boolean.class;
328                } else if ( child.getNodeName().equals( "dateTime.iso8601" ) ) {
329                    String s = XMLTools.getRequiredStringValue( "dateTime.iso8601", null, value );
330                    o = TimeTools.createCalendar( s ).getTime();
331                    cl = Date.class;
332                } else if ( child.getNodeName().equals( "base64" ) ) {
333                } else if ( child.getNodeName().equals( "array" ) ) {
334                    o = createArray( child );
335                    cl = RPCParameter[].class;
336                }        
337                mem = new RPCMember( cl, o, name );
338            } catch (Exception e) {
339                LOG.logError( e.getMessage(), e );
340                throw new RPCException( e.toString() );
341            } 
342    
343            return mem;
344        }
345    
346        /**
347         * creates an <tt>ArrayList</tt> object from the passed <tt>Element</tt>
348         * 
349         * @param array
350         * @return created <tt>ArrayList</tt>
351         */
352        private static RPCParameter[] createArray( Element array ) throws RPCException {
353    
354            RPCParameter[] param = null;
355            try {
356                Element data = XMLTools.getChildElement( "data", null, array );
357                ElementList el = XMLTools.getChildElements( data );
358                if ( el != null ) {
359                    param = new RPCParameter[el.getLength()];
360                    for (int i = 0; i < el.getLength(); i++) {
361                        Element child = XMLTools.getFirstChildElement( el.item( i ) );
362                        Object o = null;
363                        Class cl = null;
364                        if ( child.getNodeName().equals( "struct" ) ) {
365                            o = createRPCStruct( child );
366                            cl = RPCStruct.class;
367                        } else if ( child.getNodeName().equals( "string" ) ) {
368                            o = XMLTools.getRequiredStringValue( "string", null, el.item( i ) );
369                            cl = String.class;
370                        } else if ( child.getNodeName().equals( "int" ) ) {
371                            double d = XMLTools.getRequiredNodeAsDouble( el.item( i ), "./int", nsContext );
372                            o = new Integer( (int) d );
373                            cl = Integer.class;
374                        } else if ( child.getNodeName().equals( "i4" ) ) {
375                            double d = XMLTools.getRequiredNodeAsDouble( el.item( i ), "./i4", nsContext );
376                            o = new Integer( (int) d );
377                            cl = Integer.class;
378                        } else if ( child.getNodeName().equals( "double" ) ) {
379                            double d = XMLTools.getRequiredNodeAsDouble( el.item( i ), "./double",
380                                nsContext );
381                            o = new Double( d );
382                            cl = Double.class;
383                        } else if ( child.getNodeName().equals( "boolean" ) ) {
384                            o = Boolean.valueOf( child.getFirstChild().getNodeValue().equals( "1" ) );
385                            cl = Boolean.class;
386                        } else if ( child.getNodeName().equals( "dateTime.iso8601" ) ) {
387                            String s = XMLTools.getRequiredStringValue( "dateTime.iso8601", null, el
388                                .item( i ) );
389                            o = TimeTools.createCalendar( s ).getTime();
390                            cl = Date.class;
391                        } else if ( child.getNodeName().equals( "base64" ) ) {
392                        } else if ( child.getNodeName().equals( "array" ) ) {
393                            o = createArray( child );
394                            cl = RPCParameter[].class;
395                        }
396                        param[i] = new RPCParameter( cl, o );
397                    }
398                }
399            } catch (Exception e) {
400                LOG.logError( e.getMessage(), e );
401                throw new RPCException( e.toString() );
402            }
403    
404            return param;
405        }
406    
407        /**
408         * creates an <tt>RPCFault</tt> object from the passed <tt>Element</tt>
409         * 
410         * @param fault
411         *            fault element
412         * @return created <tt>RPCFault</tt>
413         */
414        private static RPCFault createRPCFault( Element fault ) throws RPCException {
415            
416            RPCFault rpcFault = null;
417            try {
418                Element value = XMLTools.getChildElement( "value", null, fault );
419                Element child = XMLTools.getFirstChildElement( value );
420                RPCStruct struct = createRPCStruct( child );
421                String s1 = null;
422                String s2 = null;
423                Object o = struct.getMember( "faultCode" ).getValue();
424                if ( o != null ) {
425                    s1 = o.toString();
426                }
427                o = struct.getMember( "faultString" ).getValue();
428                if ( o != null ) {
429                    s2 = o.toString();
430                }
431                rpcFault = new RPCFault( s1, s2 );
432            } catch (Exception e) {
433                LOG.logError( e.getMessage(), e );
434                throw new RPCException( e.toString() );
435            }
436    
437            return rpcFault;
438        }
439    
440    }