Statistics
| Revision:

root / trunk / applications / appCatalogYNomenclatorClient / src / es / gva / cit / catalogClient / drivers / CSWCatalogServiceDriver.java @ 3073

History | View | Annotate | Download (21.1 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*
19
* For more information, contact:
20
*
21
*  Generalitat Valenciana
22
*   Conselleria d'Infraestructures i Transport
23
*   Av. Blasco Ib??ez, 50
24
*   46010 VALENCIA
25
*   SPAIN
26
*
27
*      +34 963862235
28
*   gvsig@gva.es
29
*      www.gvsig.gva.es
30
*
31
*    or
32
*
33
*   IVER T.I. S.A
34
*   Salamanca 50
35
*   46005 Valencia
36
*   Spain
37
*
38
*   +34 963163400
39
*   dac@iver.es
40
*/
41
package es.gva.cit.catalogClient.drivers;
42

    
43
import es.gva.cit.catalogClient.metadataXML.XMLNode;
44
import es.gva.cit.catalogClient.metadataXML.XMLTree;
45
import es.gva.cit.catalogClient.metadataXML.XMLTreeNumberOfRecordsAnswer;
46
import es.gva.cit.catalogClient.parsers.csw.ProtocolsOperations;
47
import es.gva.cit.catalogClient.parsers.csw.cswCapabilitiesParser;
48
import es.gva.cit.catalogClient.protocols.HTTPGetProtocol;
49
import es.gva.cit.catalogClient.protocols.HTTPPostProtocol;
50
import es.gva.cit.catalogClient.protocols.SOAPProtocol;
51
import es.gva.cit.catalogClient.querys.CSWQuery;
52
import es.gva.cit.catalogClient.querys.Query;
53
import es.gva.cit.catalogClient.utils.Strings;
54

    
55
import org.apache.commons.httpclient.NameValuePair;
56

    
57
import java.net.URL;
58
/**
59
 * This class implements the CSW protocol.
60
 * 
61
 * @see http://portal.opengeospatial.org/files/?artifact_id=5929&version=1
62
 * @author Jorge Piera Llodra (piera_jor@gva.es)
63
 */
64
public class CSWCatalogServiceDriver extends AbstractCatalogServiceDriver {
65
    private String responseHandler = null;
66
    private String hopCount = null;
67
    private String distributedSearch = null;
68
    private String constraint = null;
69
    private String[] CONSTRAINTLANGUAGE = null;
70
    private String[] elementSetName = null;
71
    private String[] typeNames = null;
72
    private String[] resultType = null;
73
    private String[] NAMESPACE = null;
74
    private String ServerProfile = "ebRIM"; //or ISO
75
    private String version = "2.0.0";
76
    private ProtocolsOperations operations = null;
77

    
78
    /*
79
     * (non-Javadoc)
80
     *
81
     * @see ICatalogServerDriver#GetCapabilities(java.lang.String,
82
     *      java.lang.String)
83
     */
84
    public XMLNode[] getCapabilities(URL url) {
85
        XMLNode[] nodes = null;
86

    
87
        System.out.println("**************GET*************");
88
        nodes = new HTTPGetProtocol().doQuery(url, getMessageCapabilities(), 0);
89

    
90
        if (nodes == null) {
91
            System.out.println("**************POST*************");
92
            nodes = new HTTPPostProtocol().doQuery(url,
93
                    getPOSTMessageCapabilities(), 0);
94

    
95
            if (nodes == null) {
96
                System.out.println("**************SOAP*************");
97
                nodes = new SOAPProtocol().doQuery(url,
98
                        getSOAPMessageCapabilities(), 0);
99

    
100
                if (nodes == null) {
101
                    return null;
102
                } else {
103
                    setCommunicationProtocol("SOAP");
104
                }
105
            } else {
106
                setCommunicationProtocol("POST");
107
            }
108
        } else {
109
            setCommunicationProtocol("GET");
110
        }
111

    
112
        return nodes;
113
    }
114

    
115
    /**
116
     * this method implements the describeRecords operation
117
     * @param url
118
     * @return
119
     */
120
    public XMLNode[] describeRecords(URL url) {
121
        //return new HTTPPostProtocol().doQuery(url, getMessageDescribeRecords(),0);
122
        return null;
123
    }
124

    
125
    /*
126
     * (non-Javadoc)
127
     *
128
     * @see ICatalogServerDriver#GetRecords(java.lang.String, java.lang.String,
129
     *      java.lang.String, int, int, java.lang.String, java.lang.String)
130
     */
131
    public XMLNode[] getRecords(URL url, Query query, int firstRecord) {
132
        setQuery(query);
133

    
134
        XMLNode[] answerNodes = null;
135
        XMLNode[] nodes = null;
136
        
137
        //if (getOperations().getGetRecords()==null)
138
                //return null;
139
        
140
        /*
141
        for (int i=0 ; i<getOperations().getGetRecords().length; i++){
142
                if (getOperations().getGetRecords()[i].equals("SOAP")){
143
                         System.out.println("**************SOAP*************");
144
                         nodes = new SOAPProtocol().doQuery(url,
145
                        getSOAPMessageRecords(getQuery(), firstRecord), firstRecord);
146
                         
147
                         setCommunicationProtocol("SOAP");
148

149
                 //We must cut the SOAP Head
150
                 nodes[0] = SOAPMessageParser.cutHead(nodes[0]);
151
                         break;
152
                }
153
    
154
            if (getOperations().getGetRecords()[i].equals("POST")){*/
155
                    System.out.println("**************POST*************");
156
                nodes = new HTTPPostProtocol().doQuery(url,
157
                        getPOSTMessageRecords(getQuery(), firstRecord), firstRecord);
158
                
159
                setCommunicationProtocol("POST");                
160
                //break;
161
            /*}
162
            if (getOperations().getGetRecords()[i].equals("GET")){
163
                    System.out.println("**************GET*************");
164
                    nodes = new HTTPGetProtocol().doQuery(url,
165
                        getMessageRecords(getQuery()), firstRecord);
166
                    
167
                    setCommunicationProtocol("GET");                    
168
                break;
169
            }
170
        }*/  
171
       
172
        if (nodes == null) 
173
                return null;
174
         
175
        int numberOfRecords = getNumberOfRecords(nodes[0]);
176

    
177
        if (numberOfRecords == -1) {
178
            return null;
179
        }
180

    
181
        answerNodes = createAnswerTree(numberOfRecords, firstRecord, nodes[0],
182
                url);
183

    
184
        return answerNodes;
185
    }
186

    
187
    /**
188
     * It returns an array of nodes with:
189
     *         1st position -> tree with information of the answer
190
     *  Next positions -> One result for each position
191
     * @param numberOfRecords
192
     * Number of records returned by the query
193
     * @param firstRecord
194
     * Number of the first record
195
     * @param node
196
     * Tree returned by the server
197
     * @param url
198
     * Server URL
199
     * @return
200
     */
201
    public XMLNode[] createAnswerTree(int numberOfRecords, int firstRecord,
202
        XMLNode node, URL url) {
203
        XMLNode[] answerNodes = null;
204

    
205
        if (numberOfRecords > 10) {
206
            answerNodes = new XMLNode[11];
207
        } else {
208
            answerNodes = new XMLNode[numberOfRecords + 1];
209
        }
210

    
211
        answerNodes[0] = XMLTreeNumberOfRecordsAnswer.getNode(numberOfRecords,
212
                firstRecord, firstRecord + numberOfRecords);
213

    
214
        XMLNode[] auxNodes = cutMetadata(node);
215

    
216
        System.out.print(firstRecord);
217
        
218
        if (getServerProfile().equals("ebRIM")) {
219
            auxNodes = getEbRIMNodes(auxNodes, url);
220
        }
221

    
222
        for (int i = 1;
223
                (i <= numberOfRecords) && (i <= 10) &&
224
                (i <= (numberOfRecords - firstRecord + 1)); i++)
225
            answerNodes[i] = auxNodes[i - 1];
226

    
227
        return answerNodes;
228
    }
229

    
230
    /**
231
     * This function retrieve the nodes for one ebRIM answer
232
     * @param nodes
233
     * Nodes of the ebRIM answer
234
     * @param nodes
235
     * Server URL
236
     * @return
237
     * Medatada Nodes.
238
     */
239
    public XMLNode[] getEbRIMNodes(XMLNode[] nodes, URL url) {
240
        XMLNode[] auxNodes = new XMLNode[nodes.length];
241

    
242
        for (int i = 0; i < nodes.length; i++) {
243
            String id = XMLTree.searchAtribute(nodes[i], "id");
244
            auxNodes[i] = new HTTPGetProtocol().doQuery(url,
245
                    getEbRIMRequestParameters(id), 0)[0];
246
        }
247

    
248
        return auxNodes;
249
    }
250

    
251
    /**
252
     * It Returns the parameters needed by getExtrinsicContent
253
     * @param id
254
     * Record id
255
     * @return
256
     */
257
    NameValuePair[] getEbRIMRequestParameters(String id) {
258
        NameValuePair nvp1 = new NameValuePair("request", "getExtrinsicContent");
259
        NameValuePair nvp2 = new NameValuePair("id", id);
260

    
261
        return new NameValuePair[] { nvp1, nvp2 };
262
    }
263
    
264
    /**
265
     * This function returns the number of records that have been retrieved.
266
     * It Reads a Node value.
267
     * @param node
268
     * The answer tree
269
     * @return
270
     * The number of records
271
     */
272
    public int getNumberOfRecords(XMLNode node){
273
            int numberOfRecords = getNumberOfRecords(node,"csw:SearchResults","numberOfRecordsMatched");
274
            if (numberOfRecords == -1)
275
                    numberOfRecords = getNumberOfRecords(node,"SearchResults","numberOfRecordsMatched");
276
            
277
            return numberOfRecords;
278
    }
279

    
280
   
281
    /**
282
     * This function finds and separates metadata from a full tree
283
     * @param node
284
     * full tree
285
     * @return
286
     * An array of trees that contain metadata.
287
     */
288
    public XMLNode[] cutMetadata(XMLNode node) {
289
        XMLNode[] auxNodes = XMLTree.searchMultipleNode(node,
290
                "csw:SearchResults->brief:MD_Metadata");
291

    
292
        if (auxNodes.length == 0) {
293
            auxNodes = XMLTree.searchMultipleNode(node,
294
                    "SearchResults->ebrim:Organization");
295
        }
296

    
297
        if (auxNodes.length == 0) {
298
            auxNodes = XMLTree.searchMultipleNode(node,
299
                    "SearchResults->wrs:WRSExtrinsicObject");
300
        }
301

    
302
        return auxNodes;
303
    }
304

    
305
   /**
306
    * It creates the name-value pairs for the getCapabilities request 
307
    * @return
308
    * Name-Value pair array
309
    */
310
    public NameValuePair[] getMessageCapabilities() {
311
        NameValuePair nvp1 = new NameValuePair("request", "getCapabilities");
312
        NameValuePair nvp2 = new NameValuePair("service", "CSW");
313
        NameValuePair nvp3 = new NameValuePair("acceptversion", this.version);
314

    
315
        return new NameValuePair[] { nvp1, nvp2, nvp3 };
316
    }
317

    
318
    /**
319
     * It creates the name-value pairs for the describeRecords request 
320
     * @return
321
     * Name-Value pair array
322
     */
323
    public NameValuePair[] getMessageDescribeRecords() {
324
        NameValuePair nvp1 = new NameValuePair("request", "describeRecord");
325
        NameValuePair nvp2 = new NameValuePair("version", this.version);
326
        NameValuePair nvp3 = new NameValuePair("outputformat",
327
                this.getOutputFormat());
328
        NameValuePair nvp4 = new NameValuePair("schemalanguage", "XMLSCHEMA");
329
        NameValuePair nvp5 = new NameValuePair("typename",
330
                this.getTypeNames()[0]);
331
        NameValuePair nvp6 = new NameValuePair("namespace",
332
                "csw:http://www.opengis.org/csw");
333

    
334
        return new NameValuePair[] { nvp1, nvp2, nvp3, nvp4, nvp5, nvp6 };
335
    }
336

    
337
    /**
338
     * It creates the name-value pairs for the getRecords request
339
     * 
340
     * @param query
341
     * It contains the fields to include in the query
342
     * @return
343
     * Name-Value pair array
344
     */
345
    public NameValuePair[] getMessageRecords(Query query) {
346
        CSWQuery cswq = new CSWQuery(query);
347

    
348
        NameValuePair nvp1 = new NameValuePair("request", "getRecords");
349
        NameValuePair nvp2 = new NameValuePair("version", this.version);
350
        NameValuePair nvp3 = new NameValuePair("service", "CSW");
351
        NameValuePair nvp4 = new NameValuePair("outputformat",
352
                this.getOutputFormat());
353
        System.out.println(this.getOutputFormat());
354

    
355
        NameValuePair nvp5 = new NameValuePair("outputschema",
356
                this.getOutputSchema()[0]);
357

    
358
        //NameValuePair nvp6= new NameValuePair("resulttype",this.getResultType()[0]);
359
        NameValuePair nvp7 = new NameValuePair("namespace",
360
                "csw:http://www.opengis.org/csw");
361
        NameValuePair nvp8 = new NameValuePair("typename",
362
                Strings.getComaSeparated(this.getTypeNames()));
363
        NameValuePair nvp9 = new NameValuePair("elementsetname", "full");
364
        NameValuePair nvp10 = new NameValuePair("constraintlanguage", "FILTER");
365
        NameValuePair nvp11 = new NameValuePair("constraint",
366
                cswq.getQuery(this.getServerProfile()));
367

    
368
        System.out.println(cswq.getQuery(this.getServerProfile()));
369

    
370
        return new NameValuePair[] {
371
            nvp1, nvp2, nvp3, nvp4, nvp5, nvp7, nvp8, nvp9, nvp10, nvp11
372
        };
373
    }
374
    
375
    /**
376
     * It creates the XML for the getCapabilities request
377
     * 
378
     * @return
379
     * Name-value pair with a XML request
380
     */
381
    public NameValuePair[] getPOSTMessageCapabilities() {
382
        String message = "<csw:GetCapabilities service=\"CSW\" version=\"2.0.0\" " +
383
            "xmlns:csw=\"http://www.opengis.net/cat/csw\" " +
384
            "xmlns:ogc=\"http://www.opengis.net/ogc\">" +
385
            "<AcceptVersions xmlns=\"http://www.opengis.net/ows\">" +
386
            "<Version>" + version + "</Version>" + "</AcceptVersions>" +
387
            "<AcceptFormats xmlns=\"http://www.opengis.net/ows\">" +
388
            "<OutputFormat>text/xml</OutputFormat>" + "</AcceptFormats>" +
389
            "</csw:GetCapabilities>";
390

    
391
        System.out.println(message);
392

    
393
        NameValuePair nvp1 = new NameValuePair("body", message);
394

    
395
        return new NameValuePair[] { nvp1 };
396
    }
397
    
398
    /**
399
     * It creates the XML for the describeRecords request
400
     * 
401
     * @return
402
     * Name-value pair with a XML request
403
     */
404
    public NameValuePair[] getPOSTDescribeRecords() {
405
        String message = "<csw:DescribeRecord " +
406
            "xmlns:csw=\"http://www.opengis.net/cat/csw\" " +
407
            "xmlns:ogc=\"http://www.opengis.net/ogc\" " + "service=\"CSW\" " +
408
            "version=" + version + " " + "outputFormat=\"test/xml\" " +
409
            "schemaLanguage=\"XMLSCHEMA\">" +
410
            "<csw:TypeName>csw:record</csw:TypeName>" +
411
            "</csw:DescribeRecord>";
412

    
413
        System.out.println(message);
414

    
415
        NameValuePair nvp1 = new NameValuePair("body", message);
416

    
417
        return new NameValuePair[] { nvp1 };
418
    }
419

    
420
    /**
421
     * It creates the XML for the getRecords request
422
     * 
423
     * @return
424
     * Name-value pair with a XML request
425
     */
426
    public NameValuePair[] getPOSTMessageRecords(Query query, int firstRecord) {
427
        CSWQuery cswq = new CSWQuery(query);
428

    
429
        String message = "<?xml version='1.0' encoding='UTF-8'?>" +
430
            "<GetRecords " + "service='CSW' " +
431
            "version='2.0.0' " + "xmlns='http://www.opengis.net/cat/csw' " +
432
            "xmlns:ogc='http://www.opengis.net/ogc' " +
433
            "xmlns:gml='http://www.opengis.net/gml' " + "startPosition='" +
434
            firstRecord + "' " + "maxRecords='10' " +
435
            "outputFormat='text/xml' " + "resultType='results'>" +
436
            "<Query typeNames='Dataset Classification Association Geometry'>" +
437
            "<ElementSetName typeNames='Dataset'>summary</ElementSetName>" +
438
            "<Constraint version='1.0.20'>" +
439
            cswq.getQuery(this.getServerProfile()) + "</Constraint>" +
440
            "</Query>" + "</GetRecords>";
441

    
442
        /*
443
        String message = "<csw:GetRecords " +
444
        "xmlns:csw=\"http://www.opengis.net/cat/csw\" " +
445
        "xmlns:ogc=\"http://www.opengis.net/ogc\" " + "service=\"CSW\" " +
446
        "version=\"2.0.0\" " + "resultType=\"results\">" +
447
        "<csw:Query typeNames=\"Dataset\">" +
448
        "<csw:ElementSetName>brief</csw:ElementSetName>" +
449
        "<csw:Constraint version=\"2.0.0\">" +
450
        cswq.getQuery(this.getServerProfile()) + "</csw:Constraint>" +
451
        "</csw:Query>" + "</csw:GetRecords>";
452
        */
453
        System.out.println(message);
454

    
455
        NameValuePair nvp1 = new NameValuePair("body", message);
456

    
457
        return new NameValuePair[] { nvp1 };
458
    }
459
    
460
    /**
461
     * It creates the SOAP message for the getCapabilities request
462
     * 
463
     * @return
464
     * String with the SOAP message
465
     */
466
    public String getSOAPMessageCapabilities() {
467
        return SOAPProtocol.setSOAPMessage(getPOSTMessageCapabilities()[0].getValue(),null);
468
    }
469

    
470
    /**
471
     * It creates the SOAP message for the describeRecords request
472
     * 
473
     * @return
474
     * String with the SOAP message
475
     */
476
    public String getSOAPMessageDescribeRecords() {
477
        return SOAPProtocol.setSOAPMessage(getPOSTDescribeRecords()[0].getValue(),null);
478
    }
479
    
480
    /**
481
     * It creates the SOAP message for the getRecords request
482
     * 
483
     * @return
484
     * String with the SOAP message
485
     */
486
    public String getSOAPMessageRecords(Query query, int firstRecord) {
487
        return SOAPProtocol.setSOAPMessage(getPOSTMessageRecords(query,
488
                firstRecord)[0].getValue(),null);
489
    }
490

    
491
    /*
492
     * (non-Javadoc)
493
     *
494
     * @see catalogClient.ICatalogServerDriver#setParameters(java.util.Properties)
495
     */
496
    public boolean setParameters(XMLNode[] nodes) {
497
        return new cswCapabilitiesParser(this).parse(nodes[0]);
498
    }
499
    
500
    /**
501
     * @param typeNames
502
     * The typeNames to set.
503
     */
504
    public void setTypeNames(String[] typeNames) {
505
        this.typeNames = typeNames;
506

    
507
        //Depending of this value, the CSW server is an ebRIM or an
508
        //ISO19115/19119 server. We must to set it.
509
        for (int i = 0; i < typeNames.length; i++)
510
            if (typeNames[i].equals("csw:Record") ||
511
                    typeNames[i].equals("Record")) {
512
                setServerProfile("ISO");
513
                break;
514
            } else {
515
                setServerProfile("ebRIM");
516
            }
517
    }
518
    
519
    /* (non-Javadoc)
520
     * @see es.gva.cit.catalogClient.drivers.ICatalogServiveDriver#isTheProtocol(java.net.URL)
521
     */
522
    public boolean isProtocolSupported(URL url) {
523
        return true;
524
    }
525

    
526
    /**
527
     * @return Returns the distributedSearch.
528
     */
529
    public String getDistributedSearch() {
530
        return distributedSearch;
531
    }
532

    
533
    /**
534
     * @param distributedSearch
535
     *            The distributedSearch to set.
536
     */
537
    public void setDistributedSearch(String distributedSearch) {
538
        this.distributedSearch = distributedSearch;
539
    }
540

    
541
    /**
542
     * @return Returns the hopCount.
543
     */
544
    public String getHopCount() {
545
        return hopCount;
546
    }
547

    
548
    /**
549
     * @param hopCount
550
     *            The hopCount to set.
551
     */
552
    public void setHopCount(String hopCount) {
553
        this.hopCount = hopCount;
554
    }
555

    
556
    /**
557
     * @return Returns the nAMESPACE.
558
     */
559
    public String[] getNAMESPACE() {
560
        return NAMESPACE;
561
    }
562

    
563
    /**
564
     * @param namespace
565
     *            The nAMESPACE to set.
566
     */
567
    public void setNAMESPACE(String[] namespace) {
568
        NAMESPACE = namespace;
569
    }
570

    
571
    /**
572
     * @return Returns the responseHandler.
573
     */
574
    public String getResponseHandler() {
575
        return responseHandler;
576
    }
577

    
578
    /**
579
     * @param responseHandler
580
     *            The responseHandler to set.
581
     */
582
    public void setResponseHandler(String responseHandler) {
583
        this.responseHandler = responseHandler;
584
    }
585

    
586
    /**
587
     * @return Returns the resultType.
588
     */
589
    public String[] getResultType() {
590
        return resultType;
591
    }
592

    
593
    /**
594
     * @param resultType
595
     *            The resultType to set.
596
     */
597
    public void setResultType(String[] resultType) {
598
        this.resultType = resultType;
599
    }
600

    
601
    /**
602
     * @return Returns the typeNames.
603
     */
604
    public String[] getTypeNames() {
605
        return typeNames;
606
    }
607
    /**
608
     * @return Returns the version.
609
     */
610
    public String getVersion() {
611
        return version;
612
    }
613

    
614
    /**
615
     * @param version
616
     *            The version to set.
617
     */
618
    public void setVersion(String version) {
619
        this.version = version;
620
    }
621

    
622
    /**
623
     * @return Returns the constraint.
624
     */
625
    public String getConstraint() {
626
        return constraint;
627
    }
628

    
629
    /**
630
     * @param constraint
631
     *            The constraint to set.
632
     */
633
    public void setConstraint(String constraint) {
634
        this.constraint = constraint;
635
    }
636

    
637
    /**
638
     * @return Returns the cONSTRAINTLANGUAGE.
639
     */
640
    public String[] getCONSTRAINTLANGUAGE() {
641
        return CONSTRAINTLANGUAGE;
642
    }
643

    
644
    /**
645
     * @param constraintlanguage
646
     *            The cONSTRAINTLANGUAGE to set.
647
     */
648
    public void setCONSTRAINTLANGUAGE(String[] constraintlanguage) {
649
        CONSTRAINTLANGUAGE = constraintlanguage;
650
    }
651

    
652
    /**
653
     * @return Returns the elementSetName.
654
     */
655
    public String[] getElementSetName() {
656
        return elementSetName;
657
    }
658

    
659
    /**
660
     * @param elementSetName
661
     *            The elementSetName to set.
662
     */
663
    public void setElementSetName(String[] elementSetName) {
664
        this.elementSetName = elementSetName;
665
    }
666

    
667
    /**
668
     * @return Returns the serverProfile.
669
     */
670
    public String getServerProfile() {
671
        return ServerProfile;
672
    }
673

    
674
    /**
675
     * @param serverProfile The serverProfile to set.
676
     */
677
    public void setServerProfile(String serverProfile) {
678
        ServerProfile = serverProfile;
679
    }
680
 
681
        /**
682
         * @return Returns the operations.
683
         */
684
        public ProtocolsOperations getOperations() {
685
                return operations;
686
        }
687
        /**
688
         * @param operations The operations to set.
689
         */
690
        public void setOperations(ProtocolsOperations operations) {
691
                this.operations = operations;
692
        }
693
}