Project

General

Profile

1
package eu.dnetlib.data.mapreduce.hbase.statsExport.utils;
2

    
3
import com.google.common.collect.Multimap;
4

    
5
import eu.dnetlib.data.mapreduce.util.LicenseComparator;
6
import eu.dnetlib.data.proto.DatasourceProtos.Datasource;
7
import eu.dnetlib.data.proto.DatasourceProtos.Datasource.Metadata;
8
import eu.dnetlib.data.proto.FieldTypeProtos;
9
import eu.dnetlib.data.proto.FieldTypeProtos.Qualifier;
10
import eu.dnetlib.data.proto.FieldTypeProtos.StringField;
11
import eu.dnetlib.data.proto.FieldTypeProtos.StructuredProperty;
12
import eu.dnetlib.data.proto.OafProtos.Oaf;
13
import eu.dnetlib.data.proto.OafProtos.OafEntity;
14
import eu.dnetlib.data.proto.OafProtos.OafRel;
15
import eu.dnetlib.data.proto.OrganizationProtos.Organization;
16
import eu.dnetlib.data.proto.ProjectProtos.Project;
17
import eu.dnetlib.data.proto.RelTypeProtos.RelType;
18
import eu.dnetlib.data.proto.ResultProtos.Result;
19
import eu.dnetlib.data.proto.ResultProtos.Result.Instance;
20
import org.apache.log4j.Logger;
21

    
22
import java.text.DateFormat;
23
import java.text.ParseException;
24
import java.text.SimpleDateFormat;
25
import java.util.Date;
26
import java.util.List;
27

    
28
import org.w3c.dom.Element;
29
import org.w3c.dom.NodeList;
30
import org.xml.sax.InputSource;
31
import com.sun.org.apache.xerces.internal.parsers.DOMParser;
32
import org.w3c.dom.Document;
33

    
34
/**
35
 * @author eri Simple serializer that parses input Oaf Protos and prepares them
36
 *         for sqoop
37
 */
38
public class Serializer {
39
    private static Logger logger = Logger.getLogger(Serializer.class);
40

    
41
    private String DELIM;
42
    private String ENCLOSING;
43

    
44
    public Serializer(String DELIM, String ENCLOSING) {
45
        this.DELIM = DELIM;
46
        this.ENCLOSING = ENCLOSING;
47
    }
48

    
49
    public String serialize(Oaf oaf) {
50

    
51
        switch (oaf.getKind()) {
52
            case entity:
53
                OafEntity valueEntity = oaf.getEntity();
54

    
55
                switch (valueEntity.getType()) {
56
                    case datasource:
57

    
58
                        return buildDatasource(oaf);
59

    
60
                    case organization:
61

    
62
                        return buildOrganization(oaf);
63

    
64
                    case project:
65

    
66
                        return buildProject(oaf);
67
                    case result:
68

    
69
                        return buildResult(oaf);
70
                    default:
71
                        break;
72
                }
73
                break;
74
            case relation:
75
                return buildRel(oaf.getRel());
76
        }
77

    
78
        return null;
79
    }
80

    
81
    public String serialize(OafRel oaf) {
82

    
83
        switch (oaf.getRelType()) {
84
            case resultProject:
85
                return getResultProject(oaf);
86
            default:
87
                return buildRel(oaf);
88
        }
89
    }
90

    
91
    private String buildRel(OafRel Rel) {
92
        return cleanId(Rel.getTarget()) + DELIM;
93
    }
94

    
95
    public void extractRelations(Oaf oaf, Multimap<String, String> relations) {
96
        OafEntity valueEntity = oaf.getEntity();
97
        getOriginalId(valueEntity, relations);
98

    
99
        switch (valueEntity.getType()) {
100
            case datasource:
101
                getDatasourceLanguages(valueEntity, relations);
102
                break;
103
            case result:
104
                getResultTopics(valueEntity, relations);
105
                getResultLanguages(valueEntity, relations);
106
                getResultClassifications(valueEntity, relations);
107
                getResultDatasources(valueEntity, relations);
108
                getResultConcepts(valueEntity, relations);
109
                getResultDois(valueEntity, relations);
110
                getResultCitations(valueEntity, relations);
111
                break;
112

    
113
            case project:
114
                getProjectKeywords(valueEntity, relations);
115
                getProjectSubjects(valueEntity, relations);
116
                break;
117
        }
118

    
119
    }
120

    
121
    private void getOriginalId(OafEntity oafEntity, Multimap<String, String> relations) {
122

    
123
        String relName = oafEntity.getType().toString().toLowerCase() + "Oid";
124
        for (String oid : oafEntity.getOriginalIdList()) {
125
            relations.put(relName, cleanId(oid));
126
        }
127

    
128
    }
129

    
130
    private void getProjectKeywords(OafEntity oafEntity, Multimap<String, String> relations) {
131
        relations.put("projectKeyword", getStringField(oafEntity.getProject().getMetadata().getKeywords().getValue()));
132

    
133
    }
134

    
135
    private void getProjectSubjects(OafEntity oafEntity, Multimap<String, String> relations) {
136
        for (StructuredProperty subj : oafEntity.getProject().getMetadata().getSubjectsList()) {
137
            relations.put("projectSubject", getStringField(subj.getValue()));
138
        }
139
    }
140

    
141
    private String getResultProject(OafRel oaf) {
142
        StringBuilder buff = new StringBuilder();
143
        buff.append(cleanId(oaf.getTarget())).append(DELIM);
144
        // is declared as int!!!
145
        long diff = DATEDIFF(oaf.getResultProject().getOutcome().getRelMetadata().getEnddate(), oaf.getResultProject().getOutcome().getRelMetadata().getStartdate());
146

    
147
        if (diff < 0) {
148
            diff = 0;
149
        }
150

    
151
        buff.append(getNumericField(String.valueOf(diff)));
152
        return buff.toString();
153
    }
154

    
155

    
156
    private void getDatasourceLanguages(OafEntity valueEntity, Multimap<String, String> rels) {
157
        Datasource d = valueEntity.getDatasource();
158
        Metadata metadata = d.getMetadata();
159

    
160
        for (StringField lang : metadata.getOdlanguagesList()) {
161
            rels.put("datasourceLanguage", getStringField(lang.getValue()));
162
        }
163
    }
164

    
165
    private void getResultLanguages(OafEntity valueEntity, Multimap<String, String> rels) {
166

    
167
        Result d = valueEntity.getResult();
168
        Result.Metadata metadata = d.getMetadata();
169
        if (metadata.getLanguage().getClassname() != null && !metadata.getLanguage().getClassname().isEmpty()) {
170
            rels.put("resultLanguage", getStringField(metadata.getLanguage().getClassname()));
171
        }
172

    
173
    }
174

    
175
    private void getResultDois(OafEntity valueEntity, Multimap<String, String> rels) {
176

    
177
        for (StructuredProperty pid : valueEntity.getPidList()) {
178
            rels.put("resultPid", getStringField(pid.getQualifier().getClassname()) + getStringField(pid.getValue()));
179
        }
180
    }
181

    
182
    private void getResultClassifications(OafEntity valueEntity, Multimap<String, String> rels) {
183

    
184
        Result result = valueEntity.getResult();
185

    
186
        for (Instance instance : (result.getInstanceList())) {
187
            String classification = instance.getInstancetype().getClassname();
188

    
189
            if (classification != null && !classification.isEmpty()) {
190
                rels.put("resultClassification", getStringField(instance.getInstancetype().getClassname()));
191
            }
192
        }
193
    }
194

    
195
    private void getResultConcepts(OafEntity valueEntity, Multimap<String, String> rels) {
196
        Result result = valueEntity.getResult();
197

    
198
        for (Result.Context context : result.getMetadata().getContextList()) {
199
            rels.put("resultConcept", cleanId(context.getId()));
200
        }
201
    }
202

    
203
    private void getResultDatasources(OafEntity valueEntity, Multimap<String, String> rels) {
204
        Result result = valueEntity.getResult();
205

    
206
    // hosted by
207
        for (Instance instance : (result.getInstanceList())) {
208
            String hostedBy = instance.getHostedby().getKey();
209

    
210
            if (hostedBy != null && !hostedBy.isEmpty()) {
211
                rels.put("resultDatasource", cleanId(hostedBy) + DELIM);
212
            }
213
        }
214

    
215
    // collected from
216
        for (FieldTypeProtos.KeyValue collectedFromValue : (valueEntity.getCollectedfromList())) {
217
            String collectedFrom = collectedFromValue.getKey();
218

    
219
            if (collectedFrom != null && !collectedFrom.isEmpty()) {
220
                rels.put("resultDatasource", cleanId(collectedFrom) + DELIM);
221
            }
222
        }
223
    }
224

    
225
    private void getResultTopics(OafEntity valueEntity, Multimap<String, String> rels) {
226
        Result d = valueEntity.getResult();
227
        Result.Metadata metadata = d.getMetadata();
228
        List<StructuredProperty> Topics = metadata.getSubjectList();
229

    
230
        for (StructuredProperty topic : Topics) {
231
            rels.put("resultTopic", getStringField(topic.getValue()));
232
        }
233
    }
234

    
235

    
236
    private void getResultCitations(OafEntity oafEntity, Multimap<String, String> rels) {
237
        for (FieldTypeProtos.ExtraInfo extraInfo : oafEntity.getExtraInfoList()) {
238
            if (extraInfo.getName().equals("result citations")) {
239
                DOMParser parser = new DOMParser();
240
                try {
241
                    parser.parse(new InputSource(new java.io.StringReader(extraInfo.getValue())));
242
                    Document doc = parser.getDocument();
243
                    doc.getDocumentElement().normalize();
244

    
245
                    NodeList citations = doc.getElementsByTagName("citation");
246
                    for (int temp = 0; temp < citations.getLength(); temp++) {
247
                        Element citation = (Element) citations.item(temp);
248
                        NodeList ids = citation.getElementsByTagName("id");
249
                        for(int temp1 = 0; temp1 < ids.getLength(); temp1++){
250
                            Element id = (Element) ids.item(temp1);
251
                            if(id.getAttribute("type").equals("openaire")){
252
                                //System.out.println(id.getAttribute("value"));
253
                                rels.put("resultCitation", id.getAttribute("value"));
254
                            }
255
                        }
256
                    }
257
                } catch (Exception e) {
258
                    logger.error("Error getting result citations", e);
259
                }
260
            }
261
        }
262
    }
263

    
264
    private String buildDatasource(Oaf oaf) {
265
        Metadata metadata = oaf.getEntity().getDatasource().getMetadata();
266
        StringBuilder buff = new StringBuilder();
267

    
268
        // name
269
        if (metadata.getOfficialname().getValue().equalsIgnoreCase("unknown")) {
270
            buff.append(getStringField("Unknown Repository"));
271
        } else {
272
            buff.append(getStringField(metadata.getOfficialname().getValue()));
273
        }
274

    
275
        // type
276
        if (metadata.hasDatasourcetype()) {
277
            buff.append(getStringField(metadata.getDatasourcetype().getClassname().replaceFirst(".*::", "")));
278
        }
279

    
280
        // compatibility,
281
        buff.append(getStringField(metadata.getOpenairecompatibility().getClassname()));
282

    
283
        // latitude
284
        buff.append(getLatLongField(metadata.getLatitude().getValue()));
285

    
286
        // longtitude
287
        buff.append(getLatLongField(metadata.getLongitude().getValue()));
288

    
289
        // dateofvalidation,
290
        buff.append(getStringDateField(metadata.getDateofvalidation().getValue()));
291

    
292
        // yearofvalidation,
293
        buff.append(getYearInt(metadata.getDateofvalidation().getValue()));
294

    
295
        //harvested
296
        buff.append(getStringField("false"));
297

    
298
        //piwik_id
299
        String piwik_id = "";
300
        for (String oid : oaf.getEntity().getOriginalIdList()) {
301
            if (oid.contains("piwik")) {
302
                piwik_id = oid.split(":")[1];
303
                break;
304
            }
305
        }
306
        buff.append(getStringField(cleanNumber(piwik_id)));
307

    
308
        buff.append(getStringField(metadata.getWebsiteurl().getValue()));
309

    
310
        return buff.toString();
311

    
312
    }
313

    
314
    private String buildOrganization(Oaf oaf) {
315

    
316
        StringBuilder buff = new StringBuilder();
317
        Organization.Metadata metadata = oaf.getEntity().getOrganization().getMetadata();
318

    
319
        // `name`,
320
        buff.append(getStringField(metadata.getLegalname().getValue()));
321

    
322
        // `country`,
323
        buff.append(getStringField(metadata.getCountry().getClassid()));
324

    
325
        return buff.toString();
326
    }
327

    
328
    private String buildResult(Oaf oaf) {
329
        StringBuilder buff = new StringBuilder();
330

    
331
        Result.Metadata metadata = oaf.getEntity().getResult().getMetadata();
332

    
333
        // originalId
334
        buff.append(getId(oaf)).append(DELIM);
335

    
336
        String titleString = "";
337

    
338
        if (metadata.getTitleList().size() > 0) {
339
            StructuredProperty title = metadata.getTitleList().get(0);
340

    
341
            titleString = title.getValue().replaceAll("\\s+", " ");
342
            titleString = titleString.replaceAll("\n", " ");
343
        }
344

    
345
        //  pubtitle
346
        buff.append(getStringField(titleString));
347

    
348
        //  publisher
349
        buff.append(getStringField(metadata.getPublisher().getValue()));
350

    
351
        //  journal
352
        buff.append(getStringField(metadata.getJournal().getName()));  //#null#!
353

    
354
        // year
355
        buff.append(getYearInt(metadata.getDateofacceptance().getValue()));
356

    
357
        // date
358
        buff.append(getStringDateField(metadata.getDateofacceptance().getValue()));
359

    
360
        // bestlicense
361
        buff.append(getStringField(getBestLicense(oaf.getEntity().getResult())));
362

    
363
        // type
364
        buff.append(getStringField(metadata.getResulttype().getClassname()));
365

    
366
        // embargo_end_date
367
        buff.append(getStringDateField(metadata.getEmbargoenddate().getValue()));
368

    
369
        // `authors`,
370
        int authors = metadata.getAuthorCount();
371
        String delayed = "no";
372

    
373
        for (OafRel rel : oaf.getEntity().getCachedRelList()) {
374
            if (rel.getRelType().equals(RelType.resultProject))
375
            // remember : in result Project, first id is project, second is result.
376
            {
377
                String daysfromend = getYearDifferenceInteger(rel.getResultProject().getOutcome().getRelMetadata().getEnddate(),
378
                        rel.getResultProject().getOutcome().getRelMetadata().getStartdate());
379
                if (Integer.parseInt(daysfromend) > 0) {
380
                    delayed = "yes";
381
                }
382
            }
383
        }
384

    
385
        // `delayed`,
386
        buff.append(getStringField(delayed));
387
        //authors
388
        buff.append(getNumericField(String.valueOf(authors)));
389

    
390
        String authorNames = "";
391
        for (FieldTypeProtos.Author author:metadata.getAuthorList()) {
392
            authorNames += author.getFullname() + ";";
393
        }
394

    
395
        buff.append(getStringField(authorNames));
396

    
397
        String sources = "";
398

    
399
        for (Instance instance : (oaf.getEntity().getResult().getInstanceList())) {
400
            List<String> urls = instance.getUrlList();
401
            for (String url : urls) {
402
                sources += cleanUrl(url) + " ;";
403
            }
404
        }
405

    
406
        //sources
407
        sources = ENCLOSING + sources + ENCLOSING + DELIM;
408

    
409
        buff.append(sources);
410

    
411
        boolean hasAbstract = false;
412
        for (StringField desc:metadata.getDescriptionList()) {
413
            if (desc != null && desc.getValue() != null && !desc.getValue().trim().isEmpty())
414
                hasAbstract = true;
415
        }
416

    
417
        buff.append(getStringField(Boolean.toString(hasAbstract)));
418

    
419
        return buff.toString();
420

    
421
    }
422

    
423
    private String getBestLicense(Result result) {
424
        Qualifier bestLicense = null;
425
        LicenseComparator lc = new LicenseComparator();
426
        for (Instance instance : (result.getInstanceList())) {
427
            if (lc.compare(bestLicense, instance.getAccessright()) > 0) {
428
                bestLicense = instance.getAccessright();
429
            }
430
        }
431
        if (bestLicense != null) {
432
            return bestLicense.getClassname();
433
        } else {
434
            return "";
435
        }
436
    }
437

    
438
    private String buildProject(Oaf oaf) {
439

    
440
        FundingParser fundingParser = new FundingParser(DELIM, ENCLOSING);
441
        StringBuilder buff = new StringBuilder();
442
        Project.Metadata metadata = oaf.getEntity().getProject().getMetadata();
443
        
444
        // `acronym`,
445
        String acronym = metadata.getAcronym().getValue();
446
        if (acronym.equalsIgnoreCase("UNKNOWN")) {
447
            acronym = metadata.getTitle().getValue();
448
        }
449
        buff.append(getStringField(acronym));
450

    
451
        //title
452
        buff.append(getStringField(metadata.getTitle().getValue()));
453

    
454
        //funding_lvl
455
        List<StringField> fundList = metadata.getFundingtreeList();
456
        if (!fundList.isEmpty()) // `funding_lvl0`,
457
        {
458
            //funder + 3 funding levels
459
            buff.append(fundingParser.getFundingInfo(fundList.get(0).getValue()));
460
        } else {
461
            buff.append(fundingParser.getFundingInfo(""));
462
        }
463

    
464
        //sc39
465
        String sc39 = metadata.getEcsc39().getValue();
466
        if (sc39.equalsIgnoreCase("true") || sc39.equalsIgnoreCase("t") || sc39.contains("yes")) {
467
            sc39 = "yes";
468
        } else if (sc39.equalsIgnoreCase("false") || sc39.equalsIgnoreCase("f") || sc39.contains("no")) {
469
            sc39 = "no";
470
        }
471
        buff.append(getStringField(sc39));
472

    
473
        //project_type
474
        buff.append(getStringField(metadata.getContracttype().getClassid()));
475

    
476
        // start_year
477
        buff.append(getYearInt(metadata.getStartdate().getValue()));
478

    
479
        // end_year
480
        buff.append(getYearInt(metadata.getEnddate().getValue()));
481

    
482
        // duration enddate-startdate
483
        buff.append(getYearDifferenceInteger(metadata.getEnddate().getValue(), metadata.getStartdate().getValue()));
484

    
485
        // haspubs
486
        buff.append(getStringField("no"));
487

    
488
        // numpubs
489
        buff.append(getNumericField("0"));
490

    
491
        // enddate
492
        buff.append(getStringDateField(metadata.getEnddate().getValue()));
493

    
494
        // startdate
495
        buff.append(getStringDateField(metadata.getStartdate().getValue()));
496

    
497
        // `daysforlastpub`,
498
        buff.append(getNumericField(""));
499

    
500
        // `delayedpubs`,
501
        buff.append(getNumericField(""));
502

    
503
        //call identifier
504
        buff.append(getStringField(metadata.getCallidentifier().getValue()));
505

    
506
        //code
507
        buff.append(getStringField(metadata.getCode().getValue()));
508

    
509
        return buff.toString();
510
    }
511

    
512

    
513
    private String getYearDifferenceInteger(String enddate, String startdate) {
514

    
515
        if (enddate != null && !enddate.isEmpty() && startdate != null && !startdate.isEmpty()) {
516

    
517
            String[] split = startdate.split("-");
518

    
519
            if (split.length == 0) {
520
                return ENCLOSING + "0" + ENCLOSING + DELIM;
521
            }
522

    
523
            int Startdate = Integer.parseInt(split[0]);
524

    
525
            split = enddate.split("-");
526

    
527
            if (split.length == 0) {
528
                return ENCLOSING + "0" + ENCLOSING + DELIM;
529
            }
530

    
531
            int Enddate = Integer.parseInt(split[0]);
532

    
533
            int diff = Enddate - Startdate;
534

    
535
            return ENCLOSING + diff + ENCLOSING + DELIM;
536

    
537
        }
538

    
539
        return ENCLOSING + "0" + ENCLOSING + DELIM;
540
    }
541

    
542
    private String getYearInt(String data) {
543
        if (data == null || data.isEmpty() || data.equals("-1")) {
544
            return ENCLOSING + "0" + ENCLOSING + DELIM;
545
        }
546

    
547
        String[] split = data.split("-");
548

    
549
        if (split.length == 0) {
550
            return ENCLOSING + "0" + ENCLOSING + DELIM;
551
        }
552

    
553
        String year = split[0];
554

    
555
        year = cleanNumber(year);
556

    
557
        if (year == null || year.isEmpty()) year = "0";
558

    
559
        return ENCLOSING + year + ENCLOSING + DELIM;
560

    
561
    }
562

    
563
    private String cleanNumber(String number) {
564
        number = number.replaceAll("[^A-Za-z0-9:,_]", "");
565
        return number;
566
    }
567

    
568
    private String getLatLongField(String data) {
569

    
570
        if (data == null || data.isEmpty())
571
            return ENCLOSING + "null" + ENCLOSING + DELIM;
572

    
573
        return ENCLOSING + data.replaceAll("[^-0-9.]+", "")  + ENCLOSING + DELIM;
574

    
575
    }
576

    
577
    private String getStringField(String data) {
578

    
579
        if (data == null || data.isEmpty())
580
            return ENCLOSING + "null" + ENCLOSING + DELIM;
581

    
582
        return ENCLOSING + clean(data) + ENCLOSING + DELIM;
583

    
584
    }
585

    
586
    private String getStringDateField(String data) {
587
        if (data == null || data.isEmpty() || data.equals("-1")) {
588
            return ENCLOSING + "0" + ENCLOSING + DELIM;
589
        } else {
590
            data = data.replace(DELIM, " ");
591
            data = data.replace(ENCLOSING, " ");
592
            data = data.replaceAll("\\r\\n|\\r|\\n", "");
593
            try {
594
                DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
595
                data = format.format(format.parse(data));
596
                return ENCLOSING + data + ENCLOSING + DELIM;
597
            } catch (ParseException e) {
598
                return ENCLOSING + "0" + ENCLOSING + DELIM;
599
            }
600
        }
601
    }
602

    
603
    private String getNumericField(String data) {
604
        if (data == null || data.isEmpty()) {
605
            return ENCLOSING + "0" + ENCLOSING + DELIM;
606
        } else {
607
            return ENCLOSING + data + ENCLOSING + DELIM;
608
        }
609
    }
610

    
611
    public String getId(Oaf oaf) {
612
        switch (oaf.getKind()) {
613
            case entity:
614
                return cleanId(oaf.getEntity().getId());
615
            case relation:
616
                return cleanId(oaf.getRel().getSource());
617

    
618
        }
619
        return null;
620

    
621
    }
622

    
623
    public String getId(OafRel relOaf) {
624
        return cleanId(relOaf.getSource());
625
    }
626

    
627
    private String clean(String value) {
628
        if (value != null) {
629

    
630
            value = value.replaceAll("[\"\\r\\\\;]", "");
631
            value = value.replace(DELIM, " ");
632
            value = value.replace(ENCLOSING, " ");
633
            value = value.replaceAll("\\r\\n|\\r|\\n", " ");
634

    
635
            return value;
636
        } else {
637
            return "";
638
        }
639

    
640
    }
641

    
642
    private String cleanId(String value) {
643
        if (value != null) {
644
            // DO NOT CHANGE THIS: IT REMOVES ID PREFIX ( "5|datacite____::" to "datacite____::")
645
            // AND REPLACES OCCURRENCES OF DELIM CHARS IN DATA
646
            value = value.replaceFirst(".*\\|", "");
647
            value = value.replace("\n", "");
648
            value = value.replace(ENCLOSING, "");
649
            value = value.replace(DELIM, "");
650
            value = value.replace("\"", "");
651
            value = value.replace("«", " ");
652
            value = value.replace("»", " ");
653
        }
654

    
655
        return ENCLOSING + value + ENCLOSING;
656
    }
657

    
658
    private String cleanUrl(String value) {
659
        value = value.replace(DELIM, " ");
660
        value = value.replace(ENCLOSING, " ");
661
        value = value.replace(" ", "");
662
        value = value.replace("\n", "");
663
        value = value.replace("\r", "");
664
        value = value.replace("\\n", "");
665
        value = value.replace("\\r", "");
666
        return value;
667
    }
668

    
669
    private long DATEDIFF(String startDate, String endDate) {
670
        long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000L;
671
        long days;
672
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); // "dd/MM/yyyy HH:mm:ss");
673
        // <startdate>2011-09-01</startdate>
674
        // <enddate>2015-08-31</enddate>
675
        Date dateIni;
676
        Date dateFin;
677

    
678
        if (startDate == null || startDate.isEmpty() || endDate == null || endDate.isEmpty()) {
679
            return 0;
680
        }
681
        try {
682
            dateIni = format.parse(startDate);
683
            dateFin = format.parse(endDate);
684
            days = (dateFin.getTime() - dateIni.getTime()) / MILLISECS_PER_DAY;
685
        } catch (Exception e) {
686

    
687
            return 0;
688
        }
689

    
690
        return days;
691
    }
692
}
(3-3/3)