Statistics
| Revision:

svn-gvsig-desktop / import / extWFS2 / src / com / iver / cit / gvsig / fmap / drivers / wfs / FMapWFSDriver.java @ 18294

History | View | Annotate | Download (17.7 KB)

1
package com.iver.cit.gvsig.fmap.drivers.wfs;
2

    
3
import java.awt.geom.Rectangle2D;
4
import java.io.File;
5
import java.io.IOException;
6
import java.net.ConnectException;
7
import java.net.URL;
8
import java.text.Collator;
9
import java.util.ArrayList;
10
import java.util.Collections;
11
import java.util.Hashtable;
12
import java.util.Iterator;
13
import java.util.Locale;
14

    
15
import org.apache.log4j.Logger;
16
import org.gvsig.remoteClient.wfs.WFSClient;
17
import org.gvsig.remoteClient.wfs.WFSFeature;
18
import org.gvsig.remoteClient.wfs.WFSServiceInformation;
19
import org.gvsig.remoteClient.wfs.WFSStatus;
20
import org.gvsig.remoteClient.wfs.exceptions.WFSException;
21
import org.gvsig.remoteClient.wms.ICancellable;
22

    
23
import com.hardcode.gdbms.engine.data.DataSourceFactory;
24
import com.hardcode.gdbms.engine.data.driver.ObjectDriver;
25
import com.hardcode.gdbms.engine.data.edition.DataWare;
26
import com.hardcode.gdbms.engine.values.Value;
27
import com.iver.cit.gvsig.fmap.DriverException;
28
import com.iver.cit.gvsig.fmap.core.FShape;
29
import com.iver.cit.gvsig.fmap.core.IGeometry;
30
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
31
import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
32
import com.iver.cit.gvsig.fmap.drivers.UnsupportedVersionException;
33
import com.iver.cit.gvsig.fmap.drivers.WFSDriver;
34
import com.iver.cit.gvsig.fmap.drivers.WFSDriverException;
35
import com.iver.cit.gvsig.fmap.drivers.gml.GMLDriver;
36
import com.iver.cit.gvsig.fmap.drivers.gml.IGMLDriver;
37
import com.iver.cit.gvsig.fmap.edition.IWriteable;
38
import com.iver.cit.gvsig.fmap.edition.IWriter;
39
import com.iver.cit.gvsig.fmap.edition.wfs.FmapWFSWriter;
40
import com.iver.cit.gvsig.fmap.edition.wfs.WFSTLockFeaturesException;
41
import com.iver.cit.gvsig.fmap.layers.WFSLayerNode;
42
import com.iver.utiles.StringComparator;
43
import com.iver.utiles.StringComparator.LocaleRules;
44
import com.iver.utiles.extensionPoints.ExtensionPoint;
45
import com.iver.utiles.extensionPoints.ExtensionPointsSingleton;
46

    
47
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
48
 *
49
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
50
 *
51
 * This program is free software; you can redistribute it and/or
52
 * modify it under the terms of the GNU General Public License
53
 * as published by the Free Software Foundation; either version 2
54
 * of the License, or (at your option) any later version.
55
 *
56
 * This program is distributed in the hope that it will be useful,
57
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
59
 * GNU General Public License for more details.
60
 *
61
 * You should have received a copy of the GNU General Public License
62
 * along with this program; if not, write to the Free Software
63
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
64
 *
65
 * For more information, contact:
66
 *
67
 *  Generalitat Valenciana
68
 *   Conselleria d'Infraestructures i Transport
69
 *   Av. Blasco Ib??ez, 50
70
 *   46010 VALENCIA
71
 *   SPAIN
72
 *
73
 *      +34 963862235
74
 *   gvsig@gva.es
75
 *      www.gvsig.gva.es
76
 *
77
 *    or
78
 *
79
 *   IVER T.I. S.A
80
 *   Salamanca 50
81
 *   46005 Valencia
82
 *   Spain
83
 *
84
 *   +34 963163400
85
 *   dac@iver.es
86
 */
87
/* CVS MESSAGES:
88
 *
89
 * $Id: FMapWFSDriver.java 18294 2008-01-24 17:17:50Z jpiera $
90
 * $Log$
91
 * Revision 1.18.2.5  2006-11-17 11:28:45  ppiqueras
92
 * Corregidos bugs y a?adida nueva funcionalidad.
93
 *
94
 * Revision 1.22  2006/11/16 13:31:10  jorpiell
95
 * Se ha eliminado la visivilidad del constructor
96
 *
97
 * Revision 1.21  2006/11/15 17:38:08  jorpiell
98
 * Ya se puede guardar una capa en WFS.
99
 *
100
 * Revision 1.20  2006/09/25 10:23:03  caballero
101
 * no multiType
102
 *
103
 * Revision 1.19  2006/09/18 12:07:31  jorpiell
104
 * Se ha sustituido geotools por el driver de remoteservices
105
 *
106
 * Revision 1.18  2006/07/24 08:27:35  jorpiell
107
 * Implementado el m?todo getFieldType que permite la exportaci?n a los diferentes tipos de ficheros (como shp,....)
108
 *
109
 * Revision 1.17  2006/07/21 10:02:43  caballero
110
 * soluci?n provisional a WFS
111
 *
112
 * Revision 1.16  2006/07/12 11:55:22  jmvivo
113
 * *** empty log message ***
114
 *
115
 * Revision 1.15  2006/07/12 10:58:10  jmvivo
116
 * A?adido el metodo 'reload' del ObjectDriver (falta implementar)
117
 *
118
 * Revision 1.14  2006/07/11 11:55:41  jorpiell
119
 * Se ha a?adido el fallo de tipo de dato en el log
120
 *
121
 * Revision 1.13  2006/06/15 10:34:12  jorpiell
122
 * Ya se pueden ver los atributos de las tablas
123
 *
124
 * Revision 1.12  2006/06/15 07:50:58  jorpiell
125
 * A?adida la funcionalidad de reproyectar y hechos algunos cambios en la interfaz
126
 *
127
 * Revision 1.11  2006/06/14 08:46:24  jorpiell
128
 * Se tiene en cuanta la opcion para refrescar las capabilities
129
 *
130
 * Revision 1.10  2006/06/14 07:57:19  jorpiell
131
 * Ya no se usa la estrategia ni se usa geotools para hacer el getFeature. Ahora se usa ?nicamente para el parseo de GML
132
 *
133
 * Revision 1.9  2006/06/05 16:49:42  caballero
134
 * poder editar y exportar
135
 *
136
 * Revision 1.8  2006/05/30 05:26:38  jorpiell
137
 * isWritable ha sido a?adido a la interfaz, y hay que implementarlo
138
 *
139
 * Revision 1.7  2006/05/25 10:32:11  jorpiell
140
 * Se ha renombrado la clase WFSFields por WFSAttributes porque era algo confusa
141
 *
142
 * Revision 1.6  2006/05/23 13:21:28  jorpiell
143
 * Se tiene en cuanta el online resource
144
 *
145
 * Revision 1.5  2006/05/22 10:31:35  jorpiell
146
 * Cambio producido al cambiar una interfaz del geotools driver
147
 *
148
 * Revision 1.4  2006/05/22 10:11:10  jorpiell
149
 * Eliminadas algunas lineas innecesarias
150
 *
151
 * Revision 1.3  2006/05/19 12:53:54  jorpiell
152
 * Se le ha a?adido un driver de geottols, por lo que tiene dos drivers. Para hacer el getFeatureInfo y el capablities utilizar? elremoteServices y para hacer el getFeature usar? el de geotools.
153
 *
154
 * Revision 1.2  2006/04/20 16:38:24  jorpiell
155
 * Ahora mismo ya se puede hacer un getCapabilities y un getDescribeType de la capa seleccionada para ver los atributos a dibujar. Queda implementar el panel de opciones y hacer el getFeature().
156
 *
157
 * Revision 1.1  2006/04/19 12:50:16  jorpiell
158
 * Primer commit de la aplicaci?n. Se puede hacer un getCapabilities y ver el mensaje de vienvenida del servidor
159
 *
160
 *
161
 */
162
/**
163
 * @author Jorge Piera Llodr? (piera_jor@gva.es)
164
 */
165
public class FMapWFSDriver implements WFSDriver, BoundedShapes,ObjectDriver,IWriteable{
166
        private WFSClient remoteServicesClient;
167
        private WFSLayerNode[] featuresList;
168
        private Hashtable hashFeatures;
169
        private DriverAttributes attr = new DriverAttributes();
170
        private IGMLDriver driver = null;
171
        private boolean hasGeometry = false;
172
        //The GML driver to use
173
        private static Class gmlDriverClass = null;   
174
        //WFSTDriver
175
        private FmapWFSWriter writer = null;
176
        private WFSStatus status = null;
177
        private boolean isWfstEditing = false;
178
        
179
        FMapWFSDriver() {
180
                super();                
181
        }
182

    
183
        //Method used to register the GML parser
184
        public static void registerGmlDriver(Class clazz){
185
                gmlDriverClass = clazz;
186
        }
187

    
188
        /*
189
         *  (non-Javadoc)
190
         * @see com.iver.cit.gvsig.fmap.drivers.WFSDriver#getCapabilities(java.net.URL)
191
         */
192
        public void getCapabilities(URL server)
193
        throws WFSDriverException {
194
                try {
195
                        getClient(server).connect(null);
196
                } catch (Exception e) {
197
                        throw new WFSDriverException(e);
198
                }
199
        }
200

    
201
        /*
202
         *  (non-Javadoc)
203
         * @see com.iver.cit.gvsig.fmap.drivers.WFSDriver#describeFeatureType(java.lang.String)
204
         */
205
        public void describeFeatureType(String featureType,String nameSpace) throws WFSException {
206
                status = new WFSStatus(featureType,nameSpace);
207
                remoteServicesClient.describeFeatureType(status);
208
        }
209

    
210
        /*
211
         *  (non-Javadoc)
212
         * @see com.iver.cit.gvsig.fmap.drivers.WFSDriver#getFeature(org.gvsig.remoteClient.wfs.WFSStatus)
213
         */
214
        public void getFeature(WFSStatus wfsStatus) throws WFSException {
215
                //Retrieve the file
216
                File file = remoteServicesClient.getFeature(wfsStatus);
217
                try {
218
                        //Creates the driver
219
                        if (gmlDriverClass == null){
220
                                ExtensionPoint extensionPoint = (ExtensionPoint)ExtensionPointsSingleton.getInstance().get("FMAPWFSDriver");
221
                                if (extensionPoint != null){
222
                                        driver = (IGMLDriver)extensionPoint.create("FMAPWFSDriver");
223
                                }        
224
                        }        
225
                } catch (Exception e1) {
226
                        driver = new GMLDriver();
227
                }         
228
                //Reads the GML file
229
                try {                        
230
                        driver.open(file);
231
                        driver.initialize();        
232
                        hasGeometry = WFSUtils.getHasGeometry(featuresList,wfsStatus);
233
                } catch (Exception e) {
234
                        Logger.getLogger(getClass().getName()).error(e.getMessage());
235
                        throw new WFSDriverException(e);
236
                }
237
        }
238

    
239
        /*
240
         *  (non-Javadoc)
241
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getShapeType()
242
         */
243
        public int getShapeType() {
244
                //return driver.getShapeType();
245
                try {
246
                        if (getShapeCount() > 0){
247
                                return getShapeType(0);
248
                        }
249
                } catch (IOException e) {
250
                        // TODO Auto-generated catch block
251
                        e.printStackTrace();
252
                }
253
                return FShape.MULTI;
254
        }
255

    
256
        /*
257
         *  (non-Javadoc)
258
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getShapeCount()
259
         */
260
        public int getShapeCount() throws IOException {
261
                return driver.getShapeCount();
262
        }
263

    
264
        /*
265
         *  (non-Javadoc)
266
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getDriverAttributes()
267
         */
268
        public DriverAttributes getDriverAttributes() {
269
                return attr;
270
        }
271

    
272
        /*
273
         *  (non-Javadoc)
274
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getFullExtent()
275
         */
276
        public Rectangle2D getFullExtent() throws IOException {
277
                return driver.getFullExtent();
278
        }
279

    
280
        /*
281
         *  (non-Javadoc)
282
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getShape(int)
283
         */
284
        public IGeometry getShape(int index) throws IOException {
285
                return driver.getShape(index);                
286
        }
287

    
288
        /*
289
         *  (non-Javadoc)
290
         * @see com.hardcode.driverManager.Driver#getName()
291
         */
292
        public String getName() {
293
                return "WFS Driver";
294
        }
295

    
296

    
297

    
298
        /**
299
         * Devuelve WFSClient a partir de su URL.
300
         *
301
         * @param url URL.
302
         *
303
         * @return WMSClient.
304
         * @throws IOException
305
         * @throws ConnectException
306
         *
307
         * @throws UnsupportedVersionException
308
         * @throws IOException
309
         */
310
        public WFSClient getClient(URL url) throws ConnectException, IOException {
311
                if (remoteServicesClient == null) {
312
                        remoteServicesClient = new WFSClient(url.toString());
313
                }
314
                return remoteServicesClient;
315
        }
316

    
317
        /**
318
         * Creates a new instance of a WFSClient.
319
         * @param
320
         * host
321
         * @throws IOException
322
         * @throws ConnectException
323
         */
324
        public void createClient(URL host) throws ConnectException, IOException {
325
                remoteServicesClient = new WFSClient(host.toString());
326
        }
327

    
328
        /**
329
         * Establishes the connection to the WfS server. Connecting to a WFS is
330
         * an abstraction.<br>
331
         * <p>
332
         * Actually, it sends a GetCapabilities request to read the necessary
333
         * data for building further DescribeFeatureType requests.
334
         * </p>
335
         * @throws IOException, DriverException.
336
         */
337
        public boolean connect(boolean override,ICancellable cancel) throws IOException, DriverException {
338
                return remoteServicesClient.connect(override,cancel);
339
        }
340

    
341
        public boolean connect(ICancellable cancel) {
342
                return remoteServicesClient.connect(false, cancel);
343
        }
344

    
345
        /**
346
         * Returns an array of WFSLayerNode's with the descriptors of
347
         * all features (retrieved using the getCapabilities operation)
348
         * @return WFSLayerNode[]
349
         */
350
        public WFSLayerNode[] getLayerList(){
351
                if (hashFeatures == null) {
352
                        hashFeatures = new Hashtable();
353
                        Hashtable wfsFeatures  = remoteServicesClient.getFeatures();
354

    
355
                        StringComparator stringComparator = new StringComparator();
356
                    // Set spanish rules and with case sensitive
357
                        Collator collator = Collator.getInstance(new Locale("es_ES"));                
358
                        stringComparator.setLocaleRules(stringComparator.new LocaleRules(true, collator));
359
                        stringComparator.setCaseSensitive(false);
360
                        
361
                        ArrayList keysList = new ArrayList(wfsFeatures.keySet());
362
                        Collections.sort(keysList, stringComparator);
363
                        
364
                        Iterator keys = keysList.iterator();
365
                        featuresList = new WFSLayerNode[wfsFeatures.size()];
366

    
367
                        for (int i=0 ; i<wfsFeatures.size() ; i++){
368
                                WFSLayerNode lyr = new WFSLayerNode();
369
                                WFSFeature feature = (WFSFeature)wfsFeatures.get(keys.next());
370

    
371
                                lyr.setName(feature.getName());
372
                                lyr.setTitle(feature.getTitle());
373
                                lyr.setAbstract(feature.getAbstract());
374
                                lyr.setFields(feature.getFields());
375
                                lyr.setSrs(feature.getSrs());
376
                                lyr.setLatLonBbox(feature.getLatLonBbox());
377

    
378
                                featuresList[i] = lyr;
379
                                hashFeatures.put(lyr.getName(), lyr);
380
                        }
381
                }
382
                return featuresList;
383
        }
384

    
385
        /**
386
         * Returns all the feature information retrieved using a
387
         * describeFeatureTypeOpearion
388
         * @param layerName
389
         * Feature name
390
         * @return
391
         */
392
        public WFSLayerNode getLayerInfo(String layerName){
393
                WFSLayerNode lyr = (WFSLayerNode)hashFeatures.get(layerName);
394
                try {
395
                        describeFeatureType(layerName, null);
396
                        WFSFeature feature = (WFSFeature) remoteServicesClient.getFeatures().get(layerName);
397
                        lyr.setFields(feature.getFields());
398
                } catch (WFSException e) {
399
                        // The feature doesn't has fields
400
                        e.printStackTrace();
401
                }                
402
                return lyr;
403
        }
404

    
405

    
406
        /**
407
         * @return The title of the service offered by the WMS server.
408
         */
409
        public String getServiceTitle() {
410
                return remoteServicesClient.getServiceInformation().title;
411
        }
412

    
413
        /**
414
         * @return The abstract of the service offered by the WMS server.
415
         */
416
        public String getServiceAbstract() {
417
                return remoteServicesClient.getServiceInformation().abstr;
418
        }
419

    
420
        /**
421
         * @return the online resource
422
         */
423
        public String getOnlineResource(){
424
                WFSServiceInformation si = remoteServicesClient.getServiceInformation();
425
                return si.getOnline_resource();
426
        }
427

    
428
        /**
429
         *
430
         * @return the host
431
         */
432
        public String getHost(){
433
                return remoteServicesClient.getHost();
434
        }
435

    
436
        /**
437
         * @return the version of this client.
438
         */
439
        public String getVersion() {
440
                return remoteServicesClient.getVersion();
441
        }
442

    
443
        /*
444
         *  (non-Javadoc)
445
         * @see com.iver.cit.gvsig.fmap.drivers.WFSDriver#close()
446
         */
447
        public void close() {
448
                // TODO Auto-generated method stub
449

    
450
        }
451

    
452
        /*
453
         *  (non-Javadoc)
454
         * @see com.iver.cit.gvsig.fmap.drivers.WFSDriver#open()
455
         */
456
        public void open() throws DriverException {
457
                attr.setLoadedInMemory(true);
458

    
459
        }
460

    
461
        /*
462
         *  (non-Javadoc)
463
         * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
464
         */
465
        public int[] getPrimaryKeys() throws com.hardcode.gdbms.engine.data.driver.DriverException {
466
                throw new UnsupportedOperationException();
467
        }
468

    
469
        /*
470
         *  (non-Javadoc)
471
         * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
472
         */
473
        public void write(DataWare dataWare) throws com.hardcode.gdbms.engine.data.driver.DriverException {
474

    
475
        }
476

    
477
        /*
478
         *  (non-Javadoc)
479
         * @see com.hardcode.gdbms.engine.data.driver.GDBMSDriver#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
480
         */
481
        public void setDataSourceFactory(DataSourceFactory dsf) {
482
                // TODO Auto-generated method stub
483

    
484
        }
485

    
486
        /*
487
         *  (non-Javadoc)
488
         * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long, int)
489
         */
490
        public Value getFieldValue(long rowIndex, int fieldId) throws com.hardcode.gdbms.engine.data.driver.DriverException {
491
                return driver.getFieldValue(rowIndex, fieldId);
492
        }
493

    
494
        /*
495
         *  (non-Javadoc)
496
         * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
497
         */
498
        public int getFieldCount() throws com.hardcode.gdbms.engine.data.driver.DriverException {
499
                return driver.getFieldCount();
500
        }
501

    
502
        /*
503
         *  (non-Javadoc)
504
         * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
505
         */
506
        public String getFieldName(int fieldId) throws com.hardcode.gdbms.engine.data.driver.DriverException {
507
                return driver.getFieldName(fieldId);
508
        }
509

    
510
        /*
511
         *  (non-Javadoc)
512
         * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
513
         */
514
        public long getRowCount() throws com.hardcode.gdbms.engine.data.driver.DriverException {
515
                return driver.getRowCount();
516
        }
517

    
518
        /*
519
         *  (non-Javadoc)
520
         * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldType(int)
521
         */
522
        public int getFieldType(int i) throws com.hardcode.gdbms.engine.data.driver.DriverException {
523
                return driver.getFieldType(i);
524
        }
525

    
526
        /*
527
         *  (non-Javadoc)
528
         * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldWidth(int)
529
         */
530
        public int getFieldWidth(int i) throws com.hardcode.gdbms.engine.data.driver.DriverException {
531
                // TODO Auto-generated method stub
532
                return 100;
533
        }
534

    
535
        /*
536
         *  (non-Javadoc)
537
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#isWritable()
538
         */
539
        public boolean isWritable() {
540
                return true;
541
        }
542

    
543
        /*
544
         *  (non-Javadoc)
545
         * @see com.iver.cit.gvsig.fmap.drivers.BoundedShapes#getShapeBounds(int)
546
         */
547
        public Rectangle2D getShapeBounds(int index) throws IOException {
548
                return getShape(index).getBounds2D();
549
        }
550

    
551
        /*
552
         *  (non-Javadoc)
553
         * @see com.iver.cit.gvsig.fmap.drivers.BoundedShapes#getShapeType(int)
554
         */
555
        public int getShapeType(int index) {
556
                try {
557
                        if (getShapeCount() > 0){
558
                                return getShape(0).getGeometryType();
559
                        }
560

    
561
                } catch (IOException e) {
562
                        e.printStackTrace();
563
                }
564
                return FShape.MULTI;
565
        }
566

    
567
        /*
568
         *  (non-Javadoc)
569
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#reload()
570
         */
571
        public void reload() throws IOException, com.hardcode.gdbms.engine.data.driver.DriverException {
572
                try {
573
                        getFeature(status);
574
                } catch (WFSException e) {
575
                        throw new com.hardcode.gdbms.engine.data.driver.DriverException(e);
576
                }
577
        }
578

    
579
        /*
580
         * (non-Javadoc)
581
         * @see com.iver.cit.gvsig.fmap.edition.IWriteable#getWriter()
582
         */
583
        public IWriter getWriter() {
584
                if (writer == null){
585
                        writer = new FmapWFSWriter(this, isWfstEditing);
586
                }
587
                return writer;
588
        }
589

    
590
        /**
591
         * @return the status
592
         */
593
        public WFSStatus getStatus() {
594
                return status;
595
        }
596

    
597
        /**
598
         * @return the isWfstEditing
599
         */
600
        public boolean isWfstEditing() {
601
                return isWfstEditing;
602
        }
603

    
604
        /**
605
         * @param isWfstEditing the isWfstEditing to set
606
         */
607
        public void setWfstEditing(boolean isWfstEditing) {
608
                this.isWfstEditing = isWfstEditing;
609
                if (writer != null){
610
                        writer.setWfstEditing(isWfstEditing);
611
                }
612
        }
613
        
614
        /**
615
         * It locks all the features
616
         * @param expiryTime
617
         * The maximum time to edit
618
         * @throws WFSTLockFeaturesException 
619
         */
620
        public void lockCurrentFeatures(int expiryTime) throws WFSTLockFeaturesException{
621
                ((FmapWFSWriter)getWriter()).lockCurrentFeatures(expiryTime);
622
        }
623

    
624
        /**
625
         * @return the remoteServicesClient
626
         */
627
        public WFSClient getRemoteServicesClient() {
628
                return remoteServicesClient;
629
        }
630
}