• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IQSS / dataverse / #24275

20 Jan 2025 10:58AM UTC coverage: 22.788% (+0.04%) from 22.751%
#24275

Pull #10790

github

web-flow
Merge ed0345295 into 69ebed233
Pull Request #10790: fix: issues in exporters and citations for PermaLink/non-DOI PIDs

51 of 69 new or added lines in 7 files covered. (73.91%)

1 existing line in 1 file now uncovered.

19825 of 86999 relevant lines covered (22.79%)

0.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.15
/src/main/java/edu/harvard/iq/dataverse/export/ddi/DdiExportUtil.java
1
package edu.harvard.iq.dataverse.export.ddi;
2

3
import com.google.gson.Gson;
4

5
import edu.harvard.iq.dataverse.ControlledVocabularyValue;
6
import edu.harvard.iq.dataverse.DatasetFieldConstant;
7
import edu.harvard.iq.dataverse.DvObjectContainer;
8
import edu.harvard.iq.dataverse.GlobalId;
9
import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO;
10
import edu.harvard.iq.dataverse.api.dto.DatasetDTO;
11
import edu.harvard.iq.dataverse.api.dto.DatasetVersionDTO;
12
import edu.harvard.iq.dataverse.api.dto.FileDTO;
13
import edu.harvard.iq.dataverse.api.dto.FieldDTO;
14
import edu.harvard.iq.dataverse.api.dto.LicenseDTO;
15

16

17
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.LEVEL_FILE;
18
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_SUBJECT_TAG;
19
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_SUBJECT_UNF;
20
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_SUBJECT_FILEDESCRIPTION;
21
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_TYPE_TAG;
22
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_TYPE_UNF;
23
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_TYPE_FILEDESCRIPTION;
24
import edu.harvard.iq.dataverse.export.DDIExporter;
25
import edu.harvard.iq.dataverse.pidproviders.PidUtil;
26
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
27

28

29
import edu.harvard.iq.dataverse.util.SystemConfig;
30
import edu.harvard.iq.dataverse.util.json.JsonUtil;
31
import edu.harvard.iq.dataverse.util.xml.XmlPrinter;
32
import edu.harvard.iq.dataverse.util.xml.XmlWriterUtil;
33

34
import java.io.ByteArrayOutputStream;
35
import java.io.IOException;
36
import java.io.OutputStream;
37
import java.nio.file.Files;
38
import java.nio.file.Paths;
39
import java.time.LocalDate;
40
import java.util.*;
41
import java.util.Map.Entry;
42
import java.util.logging.Level;
43
import java.util.logging.Logger;
44
import jakarta.ejb.EJB;
45
import jakarta.json.Json;
46
import jakarta.json.JsonArray;
47
import jakarta.json.JsonArrayBuilder;
48
import jakarta.json.JsonObject;
49
import jakarta.json.JsonString;
50
import jakarta.json.JsonValue;
51
import javax.xml.stream.XMLOutputFactory;
52
import javax.xml.stream.XMLStreamException;
53
import javax.xml.stream.XMLStreamWriter;
54

55
import javax.xml.parsers.DocumentBuilder;
56
import javax.xml.parsers.DocumentBuilderFactory;
57
import javax.xml.parsers.ParserConfigurationException;
58
import org.xml.sax.SAXException;
59
import org.w3c.dom.Document;
60
import org.apache.commons.lang3.StringUtils;
61

62
// For write operation
63
import javax.xml.transform.Transformer;
64
import javax.xml.transform.TransformerException;
65
import javax.xml.transform.TransformerFactory;
66
import javax.xml.transform.TransformerConfigurationException;
67
import javax.xml.transform.dom.DOMSource;
68
import javax.xml.transform.stream.StreamSource;
69
import javax.xml.transform.stream.StreamResult;
70
import java.io.InputStream;
71

72
public class DdiExportUtil {
×
73

74
    private static final Logger logger = Logger.getLogger(DdiExportUtil.class.getCanonicalName());
1✔
75
    public static final String NOTE_TYPE_TERMS_OF_USE = "DVN:TOU";
76
    public static final String NOTE_TYPE_TERMS_OF_ACCESS = "DVN:TOA";
77
    public static final String NOTE_TYPE_DATA_ACCESS_PLACE = "DVN:DAP";
78

79

80
    public static final String LEVEL_DV = "dv";
81

82
    
83
    static SettingsServiceBean settingsService;
84
    
85
    public static final String NOTE_TYPE_CONTENTTYPE = "DATAVERSE:CONTENTTYPE";
86
    public static final String NOTE_SUBJECT_CONTENTTYPE = "Content/MIME Type";
87
    public static final String CITATION_BLOCK_NAME = "citation";
88

89
    //Some tests don't send real PIDs that can be parsed
90
    //Use constant empty PID in these cases
91
    private static final String EMPTY_PID = "null:nullnullnull";
92

93
    public static String datasetDtoAsJson2ddi(String datasetDtoAsJson) {
94
        Gson gson = new Gson();
1✔
95
        DatasetDTO datasetDto = gson.fromJson(datasetDtoAsJson, DatasetDTO.class);
1✔
96
        try {
97
            return dto2ddi(datasetDto);
1✔
98
        } catch (XMLStreamException ex) {
×
99
            Logger.getLogger(DdiExportUtil.class.getName()).log(Level.SEVERE, null, ex);
×
100
            return null;
×
101
        }
102
    }
103
    
104
    // "short" ddi, without the "<fileDscr>"  and "<dataDscr>/<var>" sections:
105
    public static void datasetJson2ddi(JsonObject datasetDtoAsJson, OutputStream outputStream) throws XMLStreamException {
106
        logger.fine(JsonUtil.prettyPrint(datasetDtoAsJson.toString()));
×
107
        Gson gson = new Gson();
×
108
        DatasetDTO datasetDto = gson.fromJson(datasetDtoAsJson.toString(), DatasetDTO.class);
×
109
        dtoddi(datasetDto, outputStream);
×
110
    }
×
111
    
112
    private static String dto2ddi(DatasetDTO datasetDto) throws XMLStreamException {
113
        OutputStream outputStream = new ByteArrayOutputStream();
1✔
114
        dtoddi(datasetDto, outputStream);
1✔
115
        String xml = outputStream.toString();
1✔
116
        return XmlPrinter.prettyPrintXml(xml);
1✔
117
    }
118
    
119
    private static void dtoddi(DatasetDTO datasetDto, OutputStream outputStream) throws XMLStreamException {
120
        XMLStreamWriter xmlw = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream);
1✔
121
        xmlw.writeStartElement("codeBook");
1✔
122
        xmlw.writeDefaultNamespace("ddi:codebook:2_5");
1✔
123
        xmlw.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
1✔
124
        xmlw.writeAttribute("xsi:schemaLocation", DDIExporter.DEFAULT_XML_NAMESPACE + " " + DDIExporter.DEFAULT_XML_SCHEMALOCATION);
1✔
125
        xmlw.writeAttribute("version", DDIExporter.DEFAULT_XML_VERSION);
1✔
126
        if(DvObjectContainer.isMetadataLanguageSet(datasetDto.getMetadataLanguage())) {
1✔
127
            xmlw.writeAttribute("xml:lang", datasetDto.getMetadataLanguage());
1✔
128
        }
129
        createStdyDscr(xmlw, datasetDto);
1✔
130
        createOtherMats(xmlw, datasetDto.getDatasetVersion().getFiles());
1✔
131
        xmlw.writeEndElement(); // codeBook
1✔
132
        xmlw.flush();
1✔
133
    }
1✔
134

135
    
136
    // "full" ddi, with the the "<fileDscr>"  and "<dataDscr>/<var>" sections: 
137
    public static void datasetJson2ddi(JsonObject datasetDtoAsJson, JsonArray fileDetails, OutputStream outputStream) throws XMLStreamException {
138
        logger.fine(JsonUtil.prettyPrint(datasetDtoAsJson.toString()));
1✔
139
        Gson gson = new Gson();
1✔
140
        DatasetDTO datasetDto = gson.fromJson(datasetDtoAsJson.toString(), DatasetDTO.class);
1✔
141
        
142
        XMLStreamWriter xmlw = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream);
1✔
143
        xmlw.writeStartElement("codeBook");
1✔
144
        xmlw.writeDefaultNamespace("ddi:codebook:2_5");
1✔
145
        xmlw.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
1✔
146
        xmlw.writeAttribute("xsi:schemaLocation", DDIExporter.DEFAULT_XML_NAMESPACE + " " + DDIExporter.DEFAULT_XML_SCHEMALOCATION);
1✔
147
        xmlw.writeAttribute("version", DDIExporter.DEFAULT_XML_VERSION);
1✔
148
        if(DvObjectContainer.isMetadataLanguageSet(datasetDto.getMetadataLanguage())) {
1✔
149
            xmlw.writeAttribute("xml:lang", datasetDto.getMetadataLanguage());
1✔
150
        }
151
        createStdyDscr(xmlw, datasetDto);
1✔
152
        createFileDscr(xmlw, fileDetails);
1✔
153
        createDataDscr(xmlw, fileDetails);
1✔
154
        createOtherMatsFromFileMetadatas(xmlw, fileDetails);
1✔
155
        xmlw.writeEndElement(); // codeBook
1✔
156
        xmlw.flush();
1✔
157
    }
1✔
158

159
    /**
160
     * @todo This is just a stub, copied from DDIExportServiceBean. It should
161
     * produce valid DDI based on
162
     * http://guides.dataverse.org/en/latest/developers/tools.html#msv but it is
163
     * incomplete and will be worked on as part of
164
     * https://github.com/IQSS/dataverse/issues/2579 . We'll want to reference
165
     * the DVN 3.x code for creating a complete DDI.
166
     *
167
     * @todo Rename this from "study" to "dataset".
168
     */
169
    private static void createStdyDscr(XMLStreamWriter xmlw, DatasetDTO datasetDto) throws XMLStreamException {
170
        DatasetVersionDTO version = datasetDto.getDatasetVersion();
1✔
171
        String persistentProtocol = datasetDto.getProtocol();
1✔
172
        String persistentAgency = persistentProtocol;
1✔
173

174
        String persistentAuthority = datasetDto.getAuthority();
1✔
175
        String persistentId = datasetDto.getIdentifier();
1✔
176

177
        GlobalId pid = PidUtil.parseAsGlobalID(persistentProtocol, persistentAuthority, persistentId);
1✔
178
        String pidUri, pidString;
179
        if(pid != null) {
1✔
180
            pidUri = pid.asURL();
1✔
181
            pidString = pid.asString();
1✔
182
        } else {
183
            pidUri = EMPTY_PID;
1✔
184
            pidString = EMPTY_PID;
1✔
185
        }
186
        // The "persistentAgency" tag is used for the "agency" attribute of the 
187
        // <IDNo> ddi section; back in the DVN3 days we used "handle" and "DOI" 
188
        // for the 2 supported protocols, respectively. For the sake of backward
189
        // compatibility, we should probably stick with these labels: (-- L.A. 4.5)
190
        if ("hdl".equals(persistentAgency)) { 
1✔
191
            persistentAgency = "handle";
×
192
        } else if ("doi".equals(persistentAgency)) {
1✔
193
            persistentAgency = "DOI";
1✔
194
        }
195
        
196
        //docDesc Block
197
        writeDocDescElement (xmlw, datasetDto);
1✔
198
        //stdyDesc Block
199
        xmlw.writeStartElement("stdyDscr");
1✔
200
        xmlw.writeStartElement("citation");
1✔
201
        xmlw.writeStartElement("titlStmt");
1✔
202
       
203
        XmlWriterUtil.writeFullElement(xmlw, "titl", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.title), datasetDto.getMetadataLanguage());
1✔
204
        XmlWriterUtil.writeFullElement(xmlw, "subTitl", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.subTitle));
1✔
205
        FieldDTO altField = dto2FieldDTO( version, DatasetFieldConstant.alternativeTitle, "citation"  );
1✔
206
        if (altField != null) {
1✔
207
            writeMultipleElement(xmlw, "altTitl", altField, datasetDto.getMetadataLanguage());
1✔
208
        }
209
        
210
        xmlw.writeStartElement("IDNo");
1✔
211
        XmlWriterUtil.writeAttribute(xmlw, "agency", persistentAgency);
1✔
212
        
213
        
214
        xmlw.writeCharacters(pidString);
1✔
215
        xmlw.writeEndElement(); // IDNo
1✔
216
        writeOtherIdElement(xmlw, version);
1✔
217
        xmlw.writeEndElement(); // titlStmt
1✔
218

219
        writeAuthorsElement(xmlw, version);
1✔
220
        writeProducersElement(xmlw, version);
1✔
221
        
222
        xmlw.writeStartElement("distStmt");
1✔
223
      //The default is to add Dataverse Repository as a distributor. The excludeinstallationifset setting turns that off if there is a distributor defined in the metadata
224
        boolean distributorSet=false;
1✔
225
        MetadataBlockDTO citationDTO= version.getMetadataBlocks().get("citation");
1✔
226
        if(citationDTO!=null) {
1✔
227
            if(citationDTO.getField(DatasetFieldConstant.distributor)!=null) {
1✔
228
                distributorSet=true;
1✔
229
            }
230
        }
231
        
232
        boolean excludeRepository = settingsService.isTrueForKey(SettingsServiceBean.Key.ExportInstallationAsDistributorOnlyWhenNotSet, false);
1✔
233
        if (!StringUtils.isEmpty(datasetDto.getPublisher()) && !(excludeRepository && distributorSet)) {
1✔
234
            xmlw.writeStartElement("distrbtr");
1✔
235
            xmlw.writeAttribute("source", "archive");
1✔
236
            xmlw.writeCharacters(datasetDto.getPublisher());
1✔
237
            xmlw.writeEndElement(); //distrbtr
1✔
238
        }
239
        writeDistributorsElement(xmlw, version, datasetDto.getMetadataLanguage());
1✔
240
        writeContactsElement(xmlw, version);
1✔
241
        /* per SCHEMA, depositr comes before depDate! - L.A. */
242
        XmlWriterUtil.writeFullElement(xmlw, "depositr", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.depositor));
1✔
243
        /* ... and depDate comes before distDate - L.A. */
244
        XmlWriterUtil.writeFullElement(xmlw, "depDate", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.dateOfDeposit));
1✔
245
        XmlWriterUtil.writeFullElement(xmlw, "distDate", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.distributionDate));
1✔
246

247
        xmlw.writeEndElement(); // diststmt
1✔
248

249
        writeSeriesElement(xmlw, version);
1✔
250
        xmlw.writeStartElement("holdings");
1✔
251
        XmlWriterUtil.writeAttribute(xmlw, "URI", pidUri);
1✔
252
        xmlw.writeEndElement(); //holdings
1✔
253
        
254
        xmlw.writeEndElement(); // citation
1✔
255
        //End Citation Block
256
        
257
        //Start Study Info Block
258
        // Study Info
259
        xmlw.writeStartElement("stdyInfo");
1✔
260
        
261
        writeSubjectElement(xmlw, version, datasetDto.getMetadataLanguage()); //Subject and Keywords
1✔
262
        writeAbstractElement(xmlw, version, datasetDto.getMetadataLanguage()); // Description
1✔
263
        writeSummaryDescriptionElement(xmlw, version, datasetDto.getMetadataLanguage());
1✔
264
        XmlWriterUtil.writeFullElement(xmlw, "notes", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.notesText));
1✔
265
        ////////
266
        xmlw.writeEndElement(); // stdyInfo
1✔
267

268
        writeMethodElement(xmlw, version, datasetDto.getMetadataLanguage());
1✔
269
        writeDataAccess(xmlw , version);
1✔
270
        writeOtherStudyMaterial(xmlw , version);
1✔
271

272
        XmlWriterUtil.writeFullElement(xmlw, "notes", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.datasetLevelErrorNotes));
1✔
273
        
274
        xmlw.writeEndElement(); // stdyDscr
1✔
275

276
    }
1✔
277

278
    private static void writeOtherStudyMaterial(XMLStreamWriter xmlw , DatasetVersionDTO version) throws XMLStreamException {
279
        List<String> relMaterials;
280
        List<String> relDatasets;
281
        List<String> relReferences;
282
        try {
283
            relMaterials = dto2PrimitiveList(version, DatasetFieldConstant.relatedMaterial);
1✔
284
            relDatasets = dto2PrimitiveList(version, DatasetFieldConstant.relatedDatasets);
1✔
285
            relReferences = dto2PrimitiveList(version, DatasetFieldConstant.otherReferences); 
1✔
286
        } catch (Exception e) {
×
287
            logger.warning("Exporting dataset to DDI failed for related materials element: " + e.getMessage());
×
288
            return;
×
289
        }
1✔
290
        xmlw.writeStartElement("othrStdyMat");
1✔
291
        XmlWriterUtil.writeFullElementList(xmlw, "relMat", relMaterials);
1✔
292
        XmlWriterUtil.writeFullElementList(xmlw, "relStdy", relDatasets);
1✔
293
        writeRelPublElement(xmlw, version);
1✔
294
        XmlWriterUtil.writeFullElementList(xmlw, "othRefs", relReferences);
1✔
295
        xmlw.writeEndElement(); //othrStdyMat
1✔
296
    }
1✔
297

298
    /*
299
            <xs:sequence>
300
               <xs:element ref="setAvail" minOccurs="0" maxOccurs="unbounded"/>
301
               <xs:element ref="useStmt" minOccurs="0" maxOccurs="unbounded"/>
302
               <xs:element ref="notes" minOccurs="0" maxOccurs="unbounded"/>
303
            </xs:sequence>
304
    */
305
    private static void writeDataAccess(XMLStreamWriter xmlw , DatasetVersionDTO version) throws XMLStreamException {
306
        xmlw.writeStartElement("dataAccs");
1✔
307
        
308
        xmlw.writeStartElement("setAvail");
1✔
309
        XmlWriterUtil.writeFullElement(xmlw, "accsPlac", version.getDataAccessPlace());
1✔
310
        XmlWriterUtil.writeFullElement(xmlw, "origArch", version.getOriginalArchive());
1✔
311
        XmlWriterUtil.writeFullElement(xmlw, "avlStatus", version.getAvailabilityStatus());
1✔
312
        XmlWriterUtil.writeFullElement(xmlw, "collSize", version.getSizeOfCollection());
1✔
313
        XmlWriterUtil.writeFullElement(xmlw, "complete", version.getStudyCompletion());
1✔
314
        xmlw.writeEndElement(); //setAvail
1✔
315
        
316
        xmlw.writeStartElement("useStmt");
1✔
317
        XmlWriterUtil.writeFullElement(xmlw, "confDec", version.getConfidentialityDeclaration());
1✔
318
        XmlWriterUtil.writeFullElement(xmlw, "specPerm", version.getSpecialPermissions());
1✔
319
        XmlWriterUtil.writeFullElement(xmlw, "restrctn", version.getRestrictions());
1✔
320
        XmlWriterUtil.writeFullElement(xmlw, "contact", version.getContactForAccess());
1✔
321
        XmlWriterUtil.writeFullElement(xmlw, "citReq", version.getCitationRequirements());
1✔
322
        XmlWriterUtil.writeFullElement(xmlw, "deposReq", version.getDepositorRequirements());
1✔
323
        XmlWriterUtil.writeFullElement(xmlw, "conditions", version.getConditions());
1✔
324
        XmlWriterUtil.writeFullElement(xmlw, "disclaimer", version.getDisclaimer());
1✔
325
        xmlw.writeEndElement(); //useStmt
1✔
326

327
        /* any <note>s: */
328
        if (version.getTermsOfUse() != null && !version.getTermsOfUse().trim().equals("")) {
1✔
329
            xmlw.writeStartElement("notes");
1✔
330
            xmlw.writeAttribute("type", NOTE_TYPE_TERMS_OF_USE);
1✔
331
            xmlw.writeAttribute("level", LEVEL_DV);
1✔
332
            xmlw.writeCharacters(version.getTermsOfUse());
1✔
333
            xmlw.writeEndElement(); //notes
1✔
334
        }
335

336
        if (version.getTermsOfAccess() != null && !version.getTermsOfAccess().trim().equals("")) {
1✔
337
            xmlw.writeStartElement("notes");
1✔
338
            xmlw.writeAttribute("type", NOTE_TYPE_TERMS_OF_ACCESS);
1✔
339
            xmlw.writeAttribute("level", LEVEL_DV);
1✔
340
            xmlw.writeCharacters(version.getTermsOfAccess());
1✔
341
            xmlw.writeEndElement(); //notes
1✔
342
        }
343

344
        LicenseDTO license = version.getLicense();
1✔
345
        if (license != null) {
1✔
346
            String name = license.getName();
1✔
347
            String uri = license.getUri();
1✔
348
            if ((name != null && !name.trim().equals("")) && (uri != null && !uri.trim().equals(""))) {
1✔
349
                xmlw.writeStartElement("notes");
1✔
350
                xmlw.writeAttribute("type", NOTE_TYPE_TERMS_OF_USE);
1✔
351
                xmlw.writeAttribute("level", LEVEL_DV);
1✔
352
                xmlw.writeCharacters("<a href=" + '"' + uri + '"' + ">" + name + "</a>");
1✔
353
                xmlw.writeEndElement(); //notes
1✔
354
            }
355
        }
356
        xmlw.writeEndElement(); //dataAccs
1✔
357
    }
1✔
358
    
359
    private static void writeDocDescElement (XMLStreamWriter xmlw, DatasetDTO datasetDto) throws XMLStreamException {
360
        DatasetVersionDTO version = datasetDto.getDatasetVersion();
1✔
361
        String persistentProtocol = datasetDto.getProtocol();
1✔
362
        String persistentAgency = persistentProtocol;
1✔
363
        // The "persistentAgency" tag is used for the "agency" attribute of the 
364
        // <IDNo> ddi section; back in the DVN3 days we used "handle" and "DOI" 
365
        // for the 2 supported protocols, respectively. For the sake of backward
366
        // compatibility, we should probably stick with these labels: (-- L.A. 4.5)
367
        if ("hdl".equals(persistentAgency)) { 
1✔
368
            persistentAgency = "handle";
×
369
        } else if ("doi".equals(persistentAgency)) {
1✔
370
            persistentAgency = "DOI";
1✔
371
        }
372
        
373
        String persistentAuthority = datasetDto.getAuthority();
1✔
374
        String persistentId = datasetDto.getIdentifier();
1✔
375
        GlobalId pid = PidUtil.parseAsGlobalID(persistentProtocol, persistentAuthority, persistentId);
1✔
376
        String pidString;
377
        if(pid != null) {
1✔
378
            pidString = pid.asString();
1✔
379
        } else {
380
            pidString = EMPTY_PID;
1✔
381
        }
382

383
        xmlw.writeStartElement("docDscr");
1✔
384
        xmlw.writeStartElement("citation");
1✔
385
        xmlw.writeStartElement("titlStmt");
1✔
386
        XmlWriterUtil.writeFullElement(xmlw, "titl", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.title), datasetDto.getMetadataLanguage());
1✔
387
        xmlw.writeStartElement("IDNo");
1✔
388
        XmlWriterUtil.writeAttribute(xmlw, "agency", persistentAgency);
1✔
389
        xmlw.writeCharacters(pidString);
1✔
390
        xmlw.writeEndElement(); // IDNo
1✔
391
        xmlw.writeEndElement(); // titlStmt
1✔
392
        xmlw.writeStartElement("distStmt");
1✔
393
        //The doc is always published by the Dataverse Repository
394
        if (!StringUtils.isEmpty(datasetDto.getPublisher())) {
1✔
395
            xmlw.writeStartElement("distrbtr");
1✔
396
            xmlw.writeAttribute("source", "archive");
1✔
397
            xmlw.writeCharacters(datasetDto.getPublisher());
1✔
398
            xmlw.writeEndElement(); // distrbtr
1✔
399
        }
400
        XmlWriterUtil.writeFullElement(xmlw, "distDate", datasetDto.getPublicationDate());
1✔
401
        
402
        xmlw.writeEndElement(); // diststmt
1✔
403
        writeVersionStatement(xmlw, version);
1✔
404
        xmlw.writeStartElement("biblCit");
1✔
405
        xmlw.writeCharacters(version.getCitation());
1✔
406
        xmlw.writeEndElement(); // biblCit
1✔
407
        xmlw.writeEndElement(); // citation      
1✔
408
        xmlw.writeEndElement(); // docDscr
1✔
409
        
410
    }
1✔
411
    
412
    private static void writeVersionStatement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException{
413
        xmlw.writeStartElement("verStmt");
1✔
414
        xmlw.writeAttribute("source","archive");
1✔
415
        xmlw.writeStartElement("version");
1✔
416
        XmlWriterUtil.writeAttribute(xmlw,"date", datasetVersionDTO.getReleaseTime().substring(0, 10));
1✔
417
        XmlWriterUtil.writeAttribute(xmlw,"type", datasetVersionDTO.getVersionState().toString());
1✔
418
        xmlw.writeCharacters(datasetVersionDTO.getVersionNumber().toString());
1✔
419
        xmlw.writeEndElement(); // version
1✔
420
        xmlw.writeEndElement(); // verStmt
1✔
421
    }
1✔
422
    
423
    /* From the DDI 2.5 schema: 
424
            <xs:sequence>
425
               <xs:element ref="timePrd" minOccurs="0" maxOccurs="unbounded"/>
426
               <xs:element ref="collDate" minOccurs="0" maxOccurs="unbounded"/>
427
               <xs:element ref="nation" minOccurs="0" maxOccurs="unbounded"/>
428
               <xs:element ref="geogCover" minOccurs="0" maxOccurs="unbounded"/>
429
               <xs:element ref="geogUnit" minOccurs="0" maxOccurs="unbounded"/>
430
               <xs:element ref="geoBndBox" minOccurs="0"/>
431
               <xs:element ref="boundPoly" minOccurs="0" maxOccurs="unbounded"/>
432
               <xs:element ref="anlyUnit" minOccurs="0" maxOccurs="unbounded"/>
433
               <xs:element ref="universe" minOccurs="0" maxOccurs="unbounded"/>
434
               <xs:element ref="dataKind" minOccurs="0" maxOccurs="unbounded"/>
435
            </xs:sequence>
436
    */
437
    private static void writeSummaryDescriptionElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException {
438
        xmlw.writeStartElement("sumDscr");
1✔
439
        FieldDTO timePeriodCoveredDTO = null;
1✔
440
        FieldDTO dateOfCollectionDTO = null;
1✔
441
        FieldDTO geographicCoverageDTO = null;
1✔
442
        FieldDTO geographicBoundingBoxDTO = null;
1✔
443
        FieldDTO unitOfAnalysisDTO = null;
1✔
444
        FieldDTO universeDTO = null;
1✔
445
        FieldDTO kindOfDataDTO = null;
1✔
446

447
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
448
            String key = entry.getKey();
1✔
449
            MetadataBlockDTO value = entry.getValue();
1✔
450

451
            if ("citation".equals(key)) {
1✔
452
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
453
                    if (DatasetFieldConstant.timePeriodCovered.equals(fieldDTO.getTypeName())) {
1✔
454
                        timePeriodCoveredDTO = fieldDTO;
1✔
455
                    }
456

457
                    if (DatasetFieldConstant.dateOfCollection.equals(fieldDTO.getTypeName())) {
1✔
458
                        dateOfCollectionDTO = fieldDTO;
1✔
459
                    }
460

461
                    if (DatasetFieldConstant.kindOfData.equals(fieldDTO.getTypeName())) {
1✔
462
                        kindOfDataDTO = fieldDTO;
1✔
463
                    }
464
                }
1✔
465
            }
466

467
            if ("geospatial".equals(key)) {
1✔
468
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
469
                    if (DatasetFieldConstant.geographicCoverage.equals(fieldDTO.getTypeName())) {
1✔
470
                        geographicCoverageDTO = fieldDTO;
1✔
471
                    }
472
                    if (DatasetFieldConstant.geographicBoundingBox.equals(fieldDTO.getTypeName())) {
1✔
473

474
                        geographicBoundingBoxDTO = fieldDTO;
1✔
475

476
                    }
477
                }
1✔
478
            }
479

480
            if ("socialscience".equals(key)) {
1✔
481
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
482
                    if (DatasetFieldConstant.universe.equals(fieldDTO.getTypeName())) {
1✔
483
                        universeDTO = fieldDTO;
1✔
484
                    }
485
                    if (DatasetFieldConstant.unitOfAnalysis.equals(fieldDTO.getTypeName())) {
1✔
486
                        unitOfAnalysisDTO = fieldDTO;
1✔
487
                    }
488
                }
1✔
489
            }
490
        }
1✔
491
        /* Finally, we can write the fields we have collected, in the correct order: -L.A.*/
492

493
        if (timePeriodCoveredDTO != null) {
1✔
494
            String dateValStart = "";
1✔
495
            String dateValEnd = "";
1✔
496
            Integer per = 0;
1✔
497
            for (HashSet<FieldDTO> foo : timePeriodCoveredDTO.getMultipleCompound()) {
1✔
498
                per++;
1✔
499
                for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
500
                    FieldDTO next = iterator.next();
1✔
501
                    if (DatasetFieldConstant.timePeriodCoveredStart.equals(next.getTypeName())) {
1✔
502
                        dateValStart = next.getSinglePrimitive();
1✔
503
                    }
504
                    if (DatasetFieldConstant.timePeriodCoveredEnd.equals(next.getTypeName())) {
1✔
505
                        dateValEnd = next.getSinglePrimitive();
1✔
506
                    }
507
                }
1✔
508
                if (!dateValStart.isEmpty()) {
1✔
509
                    writeDateElement(xmlw, "timePrd", "P" + per.toString(), "start", dateValStart);
1✔
510
                }
511
                if (!dateValEnd.isEmpty()) {
1✔
512
                    writeDateElement(xmlw, "timePrd", "P" + per.toString(), "end", dateValEnd);
1✔
513
                }
514
            }
1✔
515
        }
516

517
        if (dateOfCollectionDTO != null) {
1✔
518
            String dateValStart = "";
1✔
519
            String dateValEnd = "";
1✔
520
            Integer coll = 0;
1✔
521
            for (HashSet<FieldDTO> foo : dateOfCollectionDTO.getMultipleCompound()) {
1✔
522
                coll++;
1✔
523
                for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
524
                    FieldDTO next = iterator.next();
1✔
525
                    if (DatasetFieldConstant.dateOfCollectionStart.equals(next.getTypeName())) {
1✔
526
                        dateValStart = next.getSinglePrimitive();
1✔
527
                    }
528
                    if (DatasetFieldConstant.dateOfCollectionEnd.equals(next.getTypeName())) {
1✔
529
                        dateValEnd = next.getSinglePrimitive();
1✔
530
                    }
531
                }
1✔
532
                if (!dateValStart.isEmpty()) {
1✔
533
                    writeDateElement(xmlw, "collDate", "P" + coll.toString(), "start", dateValStart);
1✔
534
                }
535
                if (!dateValEnd.isEmpty()) {
1✔
536
                    writeDateElement(xmlw, "collDate", "P" + coll.toString(), "end", dateValEnd);
1✔
537
                }
538
            }
1✔
539
        }
540

541
        /* <nation> and <geogCover> come next, in that order. -L.A. */
542
        if (geographicCoverageDTO != null) {
1✔
543

544
            List<String> nationList = new ArrayList<>();
1✔
545
            List<String> geogCoverList = new ArrayList<>();
1✔
546

547
            for (HashSet<FieldDTO> foo : geographicCoverageDTO.getMultipleCompound()) {
1✔
548
                for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
549
                    FieldDTO next = iterator.next();
1✔
550
                    /* our "country" field maps 1:1 to the DDI "<nation>": */
551
                    if (DatasetFieldConstant.country.equals(next.getTypeName())) {
1✔
552
                        nationList.add(next.getSinglePrimitive());
1✔
553
                    }
554
                    /* city, state and otherGeographicCoverage all exported as "<geogCover>": */
555
                    if (DatasetFieldConstant.city.equals(next.getTypeName())
1✔
556
                            || DatasetFieldConstant.state.equals(next.getTypeName())
1✔
557
                            || DatasetFieldConstant.otherGeographicCoverage.equals(next.getTypeName())) {
1✔
558
                        geogCoverList.add(next.getSinglePrimitive());
1✔
559
                    }
560
                }
1✔
561
            }
1✔
562

563
            /**
564
             * And now we can write all the fields encountered, first the
565
             * "<nation>" entries, then all the "<geogCover>" ones:
566
             */
567
            for (String nationEntry : nationList) {
1✔
568
                XmlWriterUtil.writeFullElement(xmlw, "nation", nationEntry);
1✔
569
            }
1✔
570
            for (String geogCoverEntry : geogCoverList) {
1✔
571
                XmlWriterUtil.writeFullElement(xmlw, "geogCover", geogCoverEntry);
1✔
572
            }
1✔
573
        }
574

575
        XmlWriterUtil.writeFullElementList(xmlw, "geogUnit", dto2PrimitiveList(datasetVersionDTO, DatasetFieldConstant.geographicUnit));
1✔
576

577
        /* Only 1 geoBndBox is allowed in the DDI.
578
           So, I'm just going to arbitrarily use the first one, and ignore the rest! -L.A. */
579
        if (geographicBoundingBoxDTO != null) {
1✔
580
            HashSet<FieldDTO> bndBoxSet = geographicBoundingBoxDTO.getMultipleCompound().get(0);
1✔
581
            xmlw.writeStartElement("geoBndBox");
1✔
582
            HashMap<String, String> geoBndBoxMap = new HashMap<>();
1✔
583
            for (FieldDTO next : bndBoxSet) {
1✔
584
                if (DatasetFieldConstant.westLongitude.equals(next.getTypeName())) {
1✔
585
                    geoBndBoxMap.put("westBL", next.getSinglePrimitive());
1✔
586
                }
587
                if (DatasetFieldConstant.eastLongitude.equals(next.getTypeName())) {
1✔
588
                    geoBndBoxMap.put("eastBL", next.getSinglePrimitive());
1✔
589
                }
590
                if (DatasetFieldConstant.northLatitude.equals(next.getTypeName())) {
1✔
591
                    geoBndBoxMap.put("northBL", next.getSinglePrimitive());
1✔
592
                }
593
                if (DatasetFieldConstant.southLatitude.equals(next.getTypeName())) {
1✔
594
                    geoBndBoxMap.put("southBL", next.getSinglePrimitive());
1✔
595
                }
596
            }
1✔
597

598
            /* Once again, order is important! */
599
 /*
600
                        <xs:sequence>
601
                            <xs:element ref="westBL"/>
602
                            <xs:element ref="eastBL"/>
603
                            <xs:element ref="southBL"/>
604
                            <xs:element ref="northBL"/>
605
                        </xs:sequence>
606
             */
607
            if (geoBndBoxMap.get("westBL") != null) {
1✔
608
                XmlWriterUtil.writeFullElement(xmlw, "westBL", geoBndBoxMap.get("westBL"));
1✔
609
            }
610
            if (geoBndBoxMap.get("eastBL") != null) {
1✔
611
                XmlWriterUtil.writeFullElement(xmlw, "eastBL", geoBndBoxMap.get("eastBL"));
1✔
612
            }
613
            if (geoBndBoxMap.get("southBL") != null) {
1✔
614
                XmlWriterUtil.writeFullElement(xmlw, "southBL", geoBndBoxMap.get("southBL"));
1✔
615
            }
616
            if (geoBndBoxMap.get("northBL") != null) {
1✔
617
                XmlWriterUtil.writeFullElement(xmlw, "northBL", geoBndBoxMap.get("northBL"));
1✔
618
            }
619

620
            xmlw.writeEndElement();
1✔
621
        }
622

623
        /* analyUnit: */
624
        if (unitOfAnalysisDTO != null) {
1✔
625
            XmlWriterUtil.writeI18NElementList(xmlw, "anlyUnit", unitOfAnalysisDTO.getMultipleVocab(), "unitOfAnalysis", unitOfAnalysisDTO.getTypeClass(), "socialscience", lang);
1✔
626

627
        }
628

629
        /* universe: */
630
        if (universeDTO != null) {
1✔
631
            writeMultipleElement(xmlw, "universe", universeDTO, lang);
1✔
632
        }
633

634
        /* finally, any "kind of data" entries: */
635
        if (kindOfDataDTO != null) {
1✔
636
            writeMultipleElement(xmlw, "dataKind", kindOfDataDTO, lang);
1✔
637
        }
638

639
        xmlw.writeEndElement(); //sumDscr     
1✔
640
    }
1✔
641
    
642
    private static void writeMultipleElement(XMLStreamWriter xmlw, String element, FieldDTO fieldDTO, String lang) throws XMLStreamException {
643
        for (String value : fieldDTO.getMultiplePrimitive()) {
1✔
644
            //Write multiple lang vals for controlled vocab, otherwise don't include any lang tag
645
            XmlWriterUtil.writeFullElement(xmlw, element, value, fieldDTO.isControlledVocabularyField() ? lang : null);
1✔
646
        }
1✔
647
    }
1✔
648
    
649
    private static void writeDateElement(XMLStreamWriter xmlw, String element, String cycle, String event, String dateIn) throws XMLStreamException {
650

651
        xmlw.writeStartElement(element);
1✔
652
        XmlWriterUtil.writeAttribute(xmlw, "cycle",  cycle);
1✔
653
        XmlWriterUtil.writeAttribute(xmlw, "event", event);
1✔
654
        XmlWriterUtil.writeAttribute(xmlw, "date", dateIn);
1✔
655
        xmlw.writeCharacters(dateIn);
1✔
656
        xmlw.writeEndElement(); 
1✔
657

658
    }
1✔
659
    
660
    /**
661
     * Again, <dataColl> is an xs:sequence - order is important and must follow
662
     * the schema. -L.A.
663
     * <xs:sequence>
664
     * <xs:element ref="timeMeth" minOccurs="0" maxOccurs="unbounded"/>
665
     * <xs:element ref="dataCollector" minOccurs="0" maxOccurs="unbounded"/>
666
     * <xs:element ref="collectorTraining" minOccurs="0" maxOccurs="unbounded"/>
667
     * <xs:element ref="frequenc" minOccurs="0" maxOccurs="unbounded"/>
668
     * <xs:element ref="sampProc" minOccurs="0" maxOccurs="unbounded"/>
669
     * <xs:element ref="sampleFrame" minOccurs="0" maxOccurs="unbounded"/>
670
     * <xs:element ref="targetSampleSize" minOccurs="0" maxOccurs="unbounded"/>
671
     * <xs:element ref="deviat" minOccurs="0" maxOccurs="unbounded"/>
672
     * <xs:element ref="collMode" minOccurs="0" maxOccurs="unbounded"/>
673
     * <xs:element ref="resInstru" minOccurs="0" maxOccurs="unbounded"/>
674
     * <xs:element ref="instrumentDevelopment" minOccurs="0" maxOccurs="unbounded"/>
675
     * <xs:element ref="sources" minOccurs="0"/>
676
     * <xs:element ref="collSitu" minOccurs="0" maxOccurs="unbounded"/>
677
     * <xs:element ref="actMin" minOccurs="0" maxOccurs="unbounded"/>
678
     * <xs:element ref="ConOps" minOccurs="0" maxOccurs="unbounded"/>
679
     * <xs:element ref="weight" minOccurs="0" maxOccurs="unbounded"/>
680
     * <xs:element ref="cleanOps" minOccurs="0" maxOccurs="unbounded"/>
681
     * </xs:sequence>
682
     */
683
    private static void writeMethodElement(XMLStreamWriter xmlw , DatasetVersionDTO version, String lang) throws XMLStreamException{
684
        xmlw.writeStartElement("method");
1✔
685
        xmlw.writeStartElement("dataColl");
1✔
686
        XmlWriterUtil.writeI18NElement(xmlw, "timeMeth", version, DatasetFieldConstant.timeMethod,lang);
1✔
687
        XmlWriterUtil.writeI18NElement(xmlw, "dataCollector", version, DatasetFieldConstant.dataCollector, lang);
1✔
688
        XmlWriterUtil.writeI18NElement(xmlw, "collectorTraining", version, DatasetFieldConstant.collectorTraining, lang);
1✔
689
        XmlWriterUtil.writeI18NElement(xmlw, "frequenc", version, DatasetFieldConstant.frequencyOfDataCollection, lang);
1✔
690
        XmlWriterUtil.writeI18NElement(xmlw, "sampProc", version, DatasetFieldConstant.samplingProcedure, lang);
1✔
691

692
        writeTargetSampleElement(xmlw, version);
1✔
693

694
        XmlWriterUtil.writeI18NElement(xmlw, "deviat", version, DatasetFieldConstant.deviationsFromSampleDesign, lang);
1✔
695

696
        /* <collMode> comes before <sources>: */
697
        FieldDTO collModeFieldDTO = dto2FieldDTO(version, DatasetFieldConstant.collectionMode, "socialscience");
1✔
698
        if (collModeFieldDTO != null) {
1✔
699
            // This field was made multiple as of 5.10
700
            // Below is a backward compatibility check allowing export to work in 
701
            // an instance where the metadata block has not been updated yet.
702
            if (collModeFieldDTO.getMultiple()) {
1✔
703
                XmlWriterUtil.writeI18NElementList(xmlw, "collMode", collModeFieldDTO.getMultipleVocab(), DatasetFieldConstant.collectionMode, collModeFieldDTO.getTypeClass(), "socialscience", lang);
1✔
704
            } else {
705
                XmlWriterUtil.writeI18NElement(xmlw, "collMode", version, DatasetFieldConstant.collectionMode, lang);
×
706
            }
707
        }
708
        /* and so does <resInstru>: */
709
        XmlWriterUtil.writeI18NElement(xmlw, "resInstru", version, DatasetFieldConstant.researchInstrument, lang);
1✔
710
        xmlw.writeStartElement("sources");
1✔
711
        XmlWriterUtil.writeFullElementList(xmlw, "dataSrc", dto2PrimitiveList(version, DatasetFieldConstant.dataSources));
1✔
712
        XmlWriterUtil.writeI18NElement(xmlw, "srcOrig", version, DatasetFieldConstant.originOfSources, lang);
1✔
713
        XmlWriterUtil.writeI18NElement(xmlw, "srcChar", version, DatasetFieldConstant.characteristicOfSources, lang);
1✔
714
        XmlWriterUtil.writeI18NElement(xmlw, "srcDocu", version, DatasetFieldConstant.accessToSources, lang);
1✔
715
        xmlw.writeEndElement(); //sources
1✔
716

717
        
718
        XmlWriterUtil.writeI18NElement(xmlw, "collSitu", version, DatasetFieldConstant.dataCollectionSituation, lang);
1✔
719
        XmlWriterUtil.writeI18NElement(xmlw, "actMin", version, DatasetFieldConstant.actionsToMinimizeLoss, lang);
1✔
720
        /* "<ConOps>" has the uppercase C: */
721
        XmlWriterUtil.writeI18NElement(xmlw, "ConOps", version, DatasetFieldConstant.controlOperations, lang);
1✔
722
        XmlWriterUtil.writeI18NElement(xmlw, "weight", version, DatasetFieldConstant.weighting, lang);
1✔
723
        XmlWriterUtil.writeI18NElement(xmlw, "cleanOps", version, DatasetFieldConstant.cleaningOperations, lang);
1✔
724

725
        xmlw.writeEndElement(); //dataColl
1✔
726
        /* <notes> before <anlyInfo>: */
727
        writeNotesElement(xmlw, version);
1✔
728

729
        xmlw.writeStartElement("anlyInfo");
1✔
730
        //XmlWriterUtil.writeFullElement(xmlw, "anylInfo", dto2Primitive(version, DatasetFieldConstant.datasetLevelErrorNotes));
731
        XmlWriterUtil.writeI18NElement(xmlw, "respRate", version, DatasetFieldConstant.responseRate, lang);
1✔
732
        XmlWriterUtil.writeI18NElement(xmlw, "EstSmpErr", version, DatasetFieldConstant.samplingErrorEstimates, lang);
1✔
733
        XmlWriterUtil.writeI18NElement(xmlw, "dataAppr", version, DatasetFieldConstant.otherDataAppraisal, lang);
1✔
734
        xmlw.writeEndElement(); //anlyInfo
1✔
735
        
736
        xmlw.writeEndElement();//method
1✔
737
    }
1✔
738
    
739
    private static void writeSubjectElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException{ 
740
        
741
        //Key Words and Topic Classification
742
        Locale defaultLocale = Locale.getDefault();
1✔
743
        xmlw.writeStartElement("subject");
1✔
744
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
745
            String key = entry.getKey();
1✔
746
            MetadataBlockDTO value = entry.getValue();
1✔
747
            if (CITATION_BLOCK_NAME.equals(key)) {
1✔
748
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
749
                    if (DatasetFieldConstant.subject.equals(fieldDTO.getTypeName())) {
1✔
750
                        XmlWriterUtil.writeI18NElementList(xmlw, "keyword", fieldDTO.getMultipleVocab(), "subject",
1✔
751
                                fieldDTO.getTypeClass(), "citation", lang);
1✔
752
                    }
753

754
                    if (DatasetFieldConstant.keyword.equals(fieldDTO.getTypeName())) {
1✔
755
                        boolean isCVV = false;
1✔
756
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
757
                            String keywordValue = "";
1✔
758
                            String keywordVocab = "";
1✔
759
                            String keywordURI = "";
1✔
760
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
761
                                FieldDTO next = iterator.next();
1✔
762
                                if (DatasetFieldConstant.keywordValue.equals(next.getTypeName())) {
1✔
763
                                    if (next.isControlledVocabularyField()) {
1✔
764
                                        isCVV = true;
×
765
                                    }
766
                                    keywordValue = next.getSinglePrimitive();
1✔
767
                                }
768
                                if (DatasetFieldConstant.keywordVocab.equals(next.getTypeName())) {
1✔
769
                                    keywordVocab = next.getSinglePrimitive();
1✔
770
                                }
771
                                if (DatasetFieldConstant.keywordVocabURI.equals(next.getTypeName())) {
1✔
772
                                    keywordURI = next.getSinglePrimitive();
1✔
773
                                }
774
                            }
1✔
775
                            if (!keywordValue.isEmpty()) {
1✔
776
                                xmlw.writeStartElement("keyword");
1✔
777
                                XmlWriterUtil.writeAttribute(xmlw, "vocab", keywordVocab);
1✔
778
                                XmlWriterUtil.writeAttribute(xmlw, "vocabURI", keywordURI);
1✔
779
                                if (lang != null && isCVV) {
1✔
780
                                    XmlWriterUtil.writeAttribute(xmlw, "xml:lang", defaultLocale.getLanguage());
×
781
                                    xmlw.writeCharacters(ControlledVocabularyValue.getLocaleStrValue(keywordValue,
×
782
                                            DatasetFieldConstant.keywordValue, CITATION_BLOCK_NAME, defaultLocale,
783
                                            true));
784
                                } else {
785
                                    xmlw.writeCharacters(keywordValue);
1✔
786
                                }
787
                                xmlw.writeEndElement(); // Keyword
1✔
788
                                if (lang != null && isCVV && !defaultLocale.getLanguage().equals(lang)) {
1✔
789
                                    String translatedValue = ControlledVocabularyValue.getLocaleStrValue(keywordValue,
×
790
                                            DatasetFieldConstant.keywordValue, CITATION_BLOCK_NAME, new Locale(lang),
791
                                            false);
792
                                    if (translatedValue != null) {
×
793
                                        xmlw.writeStartElement("keyword");
×
794
                                        XmlWriterUtil.writeAttribute(xmlw, "vocab", keywordVocab);
×
795
                                        XmlWriterUtil.writeAttribute(xmlw, "vocabURI", keywordURI);
×
796
                                        XmlWriterUtil.writeAttribute(xmlw, "xml:lang", lang);
×
797
                                        xmlw.writeCharacters(translatedValue);
×
798
                                        xmlw.writeEndElement(); // Keyword
×
799
                                    }
800
                                }
801
                            }
802
                        }
1✔
803
                    }
804
                    if (DatasetFieldConstant.topicClassification.equals(fieldDTO.getTypeName())) {
1✔
805
                        boolean isCVV = false;
1✔
806
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
807
                            String topicClassificationValue = "";
1✔
808
                            String topicClassificationVocab = "";
1✔
809
                            String topicClassificationURI = "";
1✔
810
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
811
                                FieldDTO next = iterator.next();
1✔
812
                                if (DatasetFieldConstant.topicClassValue.equals(next.getTypeName())) {
1✔
813
                                    // Currently getSingleVocab() is the same as getSinglePrimitive() so this works
814
                                    // for either case
815
                                    topicClassificationValue = next.getSinglePrimitive();
1✔
816
                                    if (next.isControlledVocabularyField()) {
1✔
817
                                        isCVV = true;
×
818
                                    }
819
                                }
820
                                if (DatasetFieldConstant.topicClassVocab.equals(next.getTypeName())) {
1✔
821
                                    topicClassificationVocab = next.getSinglePrimitive();
1✔
822
                                }
823
                                if (DatasetFieldConstant.topicClassVocabURI.equals(next.getTypeName())) {
1✔
824
                                    topicClassificationURI = next.getSinglePrimitive();
1✔
825
                                }
826
                            }
1✔
827
                            if (!topicClassificationValue.isEmpty()) {
1✔
828
                                xmlw.writeStartElement("topcClas");
1✔
829
                                XmlWriterUtil.writeAttribute(xmlw, "vocab", topicClassificationVocab);
1✔
830
                                XmlWriterUtil.writeAttribute(xmlw, "vocabURI", topicClassificationURI);
1✔
831
                                if (lang != null && isCVV) {
1✔
832
                                    XmlWriterUtil.writeAttribute(xmlw, "xml:lang", defaultLocale.getLanguage());
×
833
                                    xmlw.writeCharacters(ControlledVocabularyValue.getLocaleStrValue(
×
834
                                            topicClassificationValue, DatasetFieldConstant.topicClassValue,
835
                                            CITATION_BLOCK_NAME, defaultLocale, true));
836
                                } else {
837
                                    xmlw.writeCharacters(topicClassificationValue);
1✔
838
                                }
839
                                xmlw.writeEndElement(); // topcClas
1✔
840
                                if (lang != null && isCVV && !defaultLocale.getLanguage().equals(lang)) {
1✔
841
                                    String translatedValue = ControlledVocabularyValue.getLocaleStrValue(
×
842
                                            topicClassificationValue, DatasetFieldConstant.topicClassValue,
843
                                            CITATION_BLOCK_NAME, new Locale(lang), false);
844
                                    if (translatedValue != null) {
×
845
                                        xmlw.writeStartElement("topcClas");
×
846
                                        XmlWriterUtil.writeAttribute(xmlw, "vocab", topicClassificationVocab);
×
847
                                        XmlWriterUtil.writeAttribute(xmlw, "vocabURI", topicClassificationURI);
×
848
                                        XmlWriterUtil.writeAttribute(xmlw, "xml:lang", lang);
×
849
                                        xmlw.writeCharacters(translatedValue);
×
850
                                        xmlw.writeEndElement(); // topcClas
×
851
                                    }
852
                                }
853
                            }
854
                        }
1✔
855
                    }
856
                }
1✔
857
            }
858
        }
1✔
859
        xmlw.writeEndElement(); // subject       
1✔
860
    }
1✔
861

862
    private static void writeAuthorsElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
863

864
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
865
            String key = entry.getKey();
1✔
866
            MetadataBlockDTO value = entry.getValue();
1✔
867
            if ("citation".equals(key)) {
1✔
868
                xmlw.writeStartElement("rspStmt");
1✔
869
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
870
                    if (DatasetFieldConstant.author.equals(fieldDTO.getTypeName())) {
1✔
871
                        String authorName = "";
1✔
872
                        String authorAffiliation = "";
1✔
873
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
874
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
875
                                FieldDTO next = iterator.next();
1✔
876
                                if (DatasetFieldConstant.authorName.equals(next.getTypeName())) {
1✔
877
                                    authorName =  next.getSinglePrimitive();
1✔
878
                                }
879
                                if (DatasetFieldConstant.authorAffiliation.equals(next.getTypeName())) {
1✔
880
                                    authorAffiliation =  next.getSinglePrimitive();
1✔
881
                                }
882
                            }
1✔
883
                            if (!authorName.isEmpty()){
1✔
884
                                xmlw.writeStartElement("AuthEnty"); 
1✔
885
                                XmlWriterUtil.writeAttribute(xmlw,"affiliation",authorAffiliation);
1✔
886
                                xmlw.writeCharacters(authorName);
1✔
887
                                xmlw.writeEndElement(); //AuthEnty
1✔
888
                            }
889
                        }
1✔
890

891
                    } else if (DatasetFieldConstant.contributor.equals(fieldDTO.getTypeName())) {
1✔
892
                        String contributorName = "";
1✔
893
                        String contributorType = "";
1✔
894
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
895
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
896
                                FieldDTO next = iterator.next();
1✔
897
                                if (DatasetFieldConstant.contributorName.equals(next.getTypeName())) {
1✔
898
                                    contributorName =  next.getSinglePrimitive();
1✔
899
                                }
900
                                if (DatasetFieldConstant.contributorType.equals(next.getTypeName())) {
1✔
901
                                    contributorType =  next.getSinglePrimitive();
1✔
902
                                }
903
                            }
1✔
904
                            if (!contributorName.isEmpty()){
1✔
905
                                xmlw.writeStartElement("othId");
1✔
906
                                XmlWriterUtil.writeAttribute(xmlw,"role", contributorType);
1✔
907
                                xmlw.writeCharacters(contributorName);
1✔
908
                                xmlw.writeEndElement(); //othId
1✔
909
                            }
910
                        }
1✔
911
                    }
912
                }
1✔
913
                xmlw.writeEndElement(); //rspStmt
1✔
914
            }
915

916
        }
1✔
917
    }
1✔
918
    
919
    private static void writeContactsElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
920

921
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
922
            String key = entry.getKey();
1✔
923
            MetadataBlockDTO value = entry.getValue();
1✔
924
            if ("citation".equals(key)) {
1✔
925
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
926
                    if (DatasetFieldConstant.datasetContact.equals(fieldDTO.getTypeName())) {
1✔
927
                        String datasetContactName = "";
1✔
928
                        String datasetContactAffiliation = "";
1✔
929
                        String datasetContactEmail = "";
1✔
930
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
931
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
932
                                FieldDTO next = iterator.next();
1✔
933
                                if (DatasetFieldConstant.datasetContactName.equals(next.getTypeName())) {
1✔
934
                                    datasetContactName =  next.getSinglePrimitive();
1✔
935
                                }
936
                                if (DatasetFieldConstant.datasetContactAffiliation.equals(next.getTypeName())) {
1✔
937
                                    datasetContactAffiliation =  next.getSinglePrimitive();
1✔
938
                                }
939
                                if (DatasetFieldConstant.datasetContactEmail.equals(next.getTypeName())) {
1✔
940
                                    datasetContactEmail = next.getSinglePrimitive();
1✔
941
                                }
942
                            }
1✔
943
                            // TODO: Since datasetContactEmail is a required field but datasetContactName is not consider not checking if datasetContactName is empty so we can write out datasetContactEmail.
944
                            if (!datasetContactName.isEmpty()){
1✔
945
                                xmlw.writeStartElement("contact"); 
1✔
946
                                XmlWriterUtil.writeAttribute(xmlw,"affiliation",datasetContactAffiliation);
1✔
947
                                XmlWriterUtil.writeAttribute(xmlw,"email",datasetContactEmail);
1✔
948
                                xmlw.writeCharacters(datasetContactName);
1✔
949
                                xmlw.writeEndElement(); //AuthEnty
1✔
950
                            }
951
                        }
1✔
952
                    }
953
                }
1✔
954
            }
955
        }
1✔
956
    }
1✔
957
    
958
    private static void writeProducersElement(XMLStreamWriter xmlw, DatasetVersionDTO version) throws XMLStreamException {
959
        xmlw.writeStartElement("prodStmt");
1✔
960
        for (Map.Entry<String, MetadataBlockDTO> entry : version.getMetadataBlocks().entrySet()) {
1✔
961
            String key = entry.getKey();
1✔
962
            MetadataBlockDTO value = entry.getValue();
1✔
963

964
            if ("citation".equals(key)) {
1✔
965
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
966
                    if (DatasetFieldConstant.producer.equals(fieldDTO.getTypeName())) {
1✔
967

968
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
969
                            String producerName = "";
1✔
970
                            String producerAffiliation = "";
1✔
971
                            String producerAbbreviation = "";
1✔
972
                            String producerLogo = "";
1✔
973
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
974
                                FieldDTO next = iterator.next();
1✔
975
                                if (DatasetFieldConstant.producerName.equals(next.getTypeName())) {
1✔
976
                                    producerName = next.getSinglePrimitive();
1✔
977
                                }
978
                                if (DatasetFieldConstant.producerAffiliation.equals(next.getTypeName())) {
1✔
979
                                    producerAffiliation = next.getSinglePrimitive();
1✔
980
                                }
981
                                if (DatasetFieldConstant.producerAbbreviation.equals(next.getTypeName())) {
1✔
982
                                    producerAbbreviation = next.getSinglePrimitive();
1✔
983
                                }
984
                                if (DatasetFieldConstant.producerLogo.equals(next.getTypeName())) {
1✔
985
                                    producerLogo = next.getSinglePrimitive();
1✔
986
                                }
987
                            }
1✔
988
                            if (!producerName.isEmpty()) {
1✔
989
                                xmlw.writeStartElement("producer");
1✔
990
                                XmlWriterUtil.writeAttribute(xmlw, "affiliation", producerAffiliation);
1✔
991
                                XmlWriterUtil.writeAttribute(xmlw, "abbr", producerAbbreviation);
1✔
992
                                //XmlWriterUtil.writeAttribute(xmlw, "role", producerLogo);
993
                                xmlw.writeCharacters(producerName);
1✔
994
                                xmlw.writeEndElement(); //AuthEnty
1✔
995
                            }
996
                        }
1✔
997
                        
998
                    }
999
                }
1✔
1000
            }
1001
        }
1✔
1002
        XmlWriterUtil.writeFullElement(xmlw, "prodDate", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.productionDate));
1✔
1003
        // productionPlace was made multiple as of 5.14:
1004
        // (a quick backward compatibility check was added to dto2PrimitiveList(),
1005
        // see the method for details)
1006

1007
        FieldDTO  prodPlac = dto2FieldDTO( version, DatasetFieldConstant.productionPlace, "citation"  );
1✔
1008
        if (prodPlac != null) {
1✔
1009
            writeMultipleElement(xmlw, "prodPlac", prodPlac, null);
1✔
1010
        }
1011
        writeSoftwareElement(xmlw, version);
1✔
1012
  
1013
        writeGrantElement(xmlw, version);
1✔
1014
        xmlw.writeEndElement(); //prodStmt
1✔
1015
    }
1✔
1016
    
1017
    private static void writeDistributorsElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException {
1018
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1019
            String key = entry.getKey();
1✔
1020
            MetadataBlockDTO value = entry.getValue();
1✔
1021
            if ("citation".equals(key)) {
1✔
1022
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1023
                    if (DatasetFieldConstant.distributor.equals(fieldDTO.getTypeName())) {
1✔
1024
                        //xmlw.writeStartElement("distrbtr");
1025
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1026
                            String distributorName = "";
1✔
1027
                            String distributorAffiliation = "";
1✔
1028
                            String distributorAbbreviation = "";
1✔
1029
                            String distributorURL = "";
1✔
1030
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1031
                                FieldDTO next = iterator.next();
1✔
1032
                                if (DatasetFieldConstant.distributorName.equals(next.getTypeName())) {
1✔
1033
                                    distributorName = next.getSinglePrimitive();
1✔
1034
                                }
1035
                                if (DatasetFieldConstant.distributorAffiliation.equals(next.getTypeName())) {
1✔
1036
                                    distributorAffiliation = next.getSinglePrimitive();
1✔
1037
                                }
1038
                                if (DatasetFieldConstant.distributorAbbreviation.equals(next.getTypeName())) {
1✔
1039
                                    distributorAbbreviation = next.getSinglePrimitive();
1✔
1040
                                }
1041
                                if (DatasetFieldConstant.distributorURL.equals(next.getTypeName())) {
1✔
1042
                                    distributorURL = next.getSinglePrimitive();
1✔
1043
                                }
1044
                            }
1✔
1045
                            if (!distributorName.isEmpty()) {
1✔
1046
                                xmlw.writeStartElement("distrbtr");
1✔
1047
                                if(DvObjectContainer.isMetadataLanguageSet(lang)) {
1✔
1048
                                    xmlw.writeAttribute("xml:lang", lang);
1✔
1049
                                }
1050
                                XmlWriterUtil.writeAttribute(xmlw, "affiliation", distributorAffiliation);
1✔
1051
                                XmlWriterUtil.writeAttribute(xmlw, "abbr", distributorAbbreviation);
1✔
1052
                                XmlWriterUtil.writeAttribute(xmlw, "URI", distributorURL);
1✔
1053
                                xmlw.writeCharacters(distributorName);
1✔
1054
                                xmlw.writeEndElement(); //AuthEnty
1✔
1055
                            }
1056
                        }
1✔
1057
                        //xmlw.writeEndElement(); //rspStmt
1058
                    }
1059

1060
                }
1✔
1061
            }
1062
        }
1✔
1063
    }
1✔
1064
    
1065
    private static void writeRelPublElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1066
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1067
            String key = entry.getKey();
1✔
1068
            MetadataBlockDTO value = entry.getValue();
1✔
1069
            if ("citation".equals(key)) {
1✔
1070
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1071
                    if (DatasetFieldConstant.publication.equals(fieldDTO.getTypeName())) {
1✔
1072
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1073
                            String pubString = "";
1✔
1074
                            String citation = "";
1✔
1075
                            String IDType = "";
1✔
1076
                            String IDNo = "";
1✔
1077
                            String url = "";
1✔
1078
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1079
                                FieldDTO next = iterator.next();
1✔
1080
                                if (DatasetFieldConstant.publicationCitation.equals(next.getTypeName())) {
1✔
1081
                                    citation =  next.getSinglePrimitive();
1✔
1082
                                }
1083
                                if (DatasetFieldConstant.publicationIDType.equals(next.getTypeName())) {
1✔
1084
                                    IDType =  next.getSinglePrimitive();
1✔
1085
                                }
1086
                                if (DatasetFieldConstant.publicationIDNumber.equals(next.getTypeName())) {
1✔
1087
                                    IDNo =   next.getSinglePrimitive();
1✔
1088
                                }
1089
                                if (DatasetFieldConstant.publicationURL.equals(next.getTypeName())) {
1✔
1090
                                    url =  next.getSinglePrimitive();
1✔
1091
                                }
1092
                            }
1✔
1093
                            if (citation != null && !citation.trim().equals("")) {
1✔
1094
                                xmlw.writeStartElement("relPubl");
1✔
1095
                                xmlw.writeStartElement("citation");
1✔
1096
                                /* <xs:sequence>
1097
                                    <xs:element ref="titlStmt"/>
1098
                                    <xs:element ref="rspStmt" minOccurs="0"/>
1099
                                    <xs:element ref="prodStmt" minOccurs="0"/>
1100
                                    <xs:element ref="distStmt" minOccurs="0"/>
1101
                                    <xs:element ref="serStmt" minOccurs="0" maxOccurs="unbounded"/>
1102
                                    <xs:element ref="verStmt" minOccurs="0" maxOccurs="unbounded"/>
1103
                                    <xs:element ref="biblCit" minOccurs="0" maxOccurs="unbounded"/>
1104
                                    <xs:element ref="holdings" minOccurs="0" maxOccurs="unbounded"/>
1105
                                    <xs:element ref="notes" minOccurs="0" maxOccurs="unbounded"/>
1106
                                    <xs:group ref="dc:elementsAndRefinementsGroup"/>
1107
                                   </xs:sequence>
1108
                                 (In other words - titlStmt is mandatory! -L.A.)
1109
                                */
1110
                                xmlw.writeStartElement("titlStmt");
1✔
1111
                                XmlWriterUtil.writeFullElement(xmlw, "titl", citation);
1✔
1112
                                if (IDNo != null && !IDNo.trim().equals("")) {
1✔
1113

1114
                                    xmlw.writeStartElement("IDNo");
1✔
1115
                                    if (IDType != null && !IDType.trim().equals("")) {
1✔
1116
                                        xmlw.writeAttribute("agency", IDType);
1✔
1117
                                    }
1118
                                    xmlw.writeCharacters(IDNo);
1✔
1119
                                    xmlw.writeEndElement(); //IDNo
1✔
1120
                                }
1121
                                xmlw.writeEndElement(); // titlStmt
1✔
1122

1123

1124
                                XmlWriterUtil.writeFullElement(xmlw,"biblCit",citation);
1✔
1125
                                xmlw.writeEndElement(); //citation
1✔
1126
                                if (url != null && !url.trim().equals("") ) {
1✔
1127
                                    xmlw.writeStartElement("ExtLink");
1✔
1128
                                    xmlw.writeAttribute("URI", url);
1✔
1129
                                    xmlw.writeEndElement(); //ExtLink
1✔
1130
                                }
1131
                                xmlw.writeEndElement(); //relPubl
1✔
1132
                            }
1133
                        }
1✔
1134
                    }
1135
                }
1✔
1136
            }
1137
        }
1✔
1138
    }
1✔
1139
    
1140
    private static String appendCommaSeparatedValue(String inVal, String next) {
1141
        if (!next.isEmpty()) {
×
1142
            if (!inVal.isEmpty()) {
×
1143
                return inVal + ", " + next;
×
1144
            } else {
1145
                return next;
×
1146
            }
1147
        }
1148
        return inVal;
×
1149
    }
1150
    
1151
    private static void writeAbstractElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException {
1152
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1153
            String key = entry.getKey();
1✔
1154
            MetadataBlockDTO value = entry.getValue();
1✔
1155
            if ("citation".equals(key)) {
1✔
1156
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1157
                    if (DatasetFieldConstant.description.equals(fieldDTO.getTypeName())) {
1✔
1158
                        String descriptionText = "";
1✔
1159
                        String descriptionDate = "";
1✔
1160
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1161
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1162
                                FieldDTO next = iterator.next();
1✔
1163
                                if (DatasetFieldConstant.descriptionText.equals(next.getTypeName())) {
1✔
1164
                                    descriptionText =  next.getSinglePrimitive();
1✔
1165
                                }
1166
                                if (DatasetFieldConstant.descriptionDate.equals(next.getTypeName())) {
1✔
1167
                                    descriptionDate =  next.getSinglePrimitive();
1✔
1168
                                }
1169
                            }
1✔
1170
                            if (!descriptionText.isEmpty()){
1✔
1171
                                xmlw.writeStartElement("abstract"); 
1✔
1172
                                XmlWriterUtil.writeAttribute(xmlw,"date",descriptionDate);
1✔
1173
                                if(DvObjectContainer.isMetadataLanguageSet(lang)) {
1✔
1174
                                    xmlw.writeAttribute("xml:lang", lang);
1✔
1175
                                }
1176
                                xmlw.writeCharacters(descriptionText);
1✔
1177
                                xmlw.writeEndElement(); //abstract
1✔
1178
                            }
1179
                        }
1✔
1180
                    }
1181
                }
1✔
1182
            }
1183
        }
1✔
1184
    }
1✔
1185

1186
    private static void writeGrantElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1187
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1188
            String key = entry.getKey();
1✔
1189
            MetadataBlockDTO value = entry.getValue();
1✔
1190
            if ("citation".equals(key)) {
1✔
1191
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1192
                    if (DatasetFieldConstant.grantNumber.equals(fieldDTO.getTypeName())) {
1✔
1193
                        String grantNumber = "";
1✔
1194
                        String grantAgency = "";
1✔
1195
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1196
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1197
                                FieldDTO next = iterator.next();
1✔
1198
                                if (DatasetFieldConstant.grantNumberValue.equals(next.getTypeName())) {
1✔
1199
                                    grantNumber =  next.getSinglePrimitive();
1✔
1200
                                }
1201
                                if (DatasetFieldConstant.grantNumberAgency.equals(next.getTypeName())) {
1✔
1202
                                    grantAgency =  next.getSinglePrimitive();
1✔
1203
                                }
1204
                            }
1✔
1205
                            if (!grantNumber.isEmpty()){
1✔
1206
                                xmlw.writeStartElement("grantNo"); 
1✔
1207
                                XmlWriterUtil.writeAttribute(xmlw,"agency",grantAgency);
1✔
1208
                                xmlw.writeCharacters(grantNumber);
1✔
1209
                                xmlw.writeEndElement(); //grantno
1✔
1210
                            }
1211
                        }
1✔
1212
                    }
1213
                }
1✔
1214
            }
1215
        }
1✔
1216
    }
1✔
1217
    
1218
    private static void writeOtherIdElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1219
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1220
            String key = entry.getKey();
1✔
1221
            MetadataBlockDTO value = entry.getValue();
1✔
1222
            if ("citation".equals(key)) {
1✔
1223
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1224
                    if (DatasetFieldConstant.otherId.equals(fieldDTO.getTypeName())) {
1✔
1225
                        String otherId = "";
1✔
1226
                        String otherIdAgency = "";
1✔
1227
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1228
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1229
                                FieldDTO next = iterator.next();
1✔
1230
                                if (DatasetFieldConstant.otherIdValue.equals(next.getTypeName())) {
1✔
1231
                                    otherId =  next.getSinglePrimitive();
1✔
1232
                                }
1233
                                if (DatasetFieldConstant.otherIdAgency.equals(next.getTypeName())) {
1✔
1234
                                    otherIdAgency =  next.getSinglePrimitive();
1✔
1235
                                }
1236
                            }
1✔
1237
                            if (!otherId.isEmpty()){
1✔
1238
                                xmlw.writeStartElement("IDNo"); 
1✔
1239
                                XmlWriterUtil.writeAttribute(xmlw,"agency",otherIdAgency);
1✔
1240
                                xmlw.writeCharacters(otherId);
1✔
1241
                                xmlw.writeEndElement(); //IDNo
1✔
1242
                            }
1243
                        }
1✔
1244
                    }
1245
                }
1✔
1246
            }
1247
        }
1✔
1248
    }
1✔
1249
    
1250
    private static void writeSoftwareElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1251
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1252
            String key = entry.getKey();
1✔
1253
            MetadataBlockDTO value = entry.getValue();
1✔
1254
            if ("citation".equals(key)) {
1✔
1255
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1256
                    if (DatasetFieldConstant.software.equals(fieldDTO.getTypeName())) {
1✔
1257
                        String softwareName = "";
1✔
1258
                        String softwareVersion = "";
1✔
1259
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1260
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1261
                                FieldDTO next = iterator.next();
1✔
1262
                                if (DatasetFieldConstant.softwareName.equals(next.getTypeName())) {
1✔
1263
                                    softwareName =  next.getSinglePrimitive();
1✔
1264
                                }
1265
                                if (DatasetFieldConstant.softwareVersion.equals(next.getTypeName())) {
1✔
1266
                                    softwareVersion =  next.getSinglePrimitive();
1✔
1267
                                }
1268
                            }
1✔
1269
                            if (!softwareName.isEmpty()){
1✔
1270
                                xmlw.writeStartElement("software"); 
1✔
1271
                                XmlWriterUtil.writeAttribute(xmlw,"version",softwareVersion);
1✔
1272
                                xmlw.writeCharacters(softwareName);
1✔
1273
                                xmlw.writeEndElement(); //software
1✔
1274
                            }
1275
                        }
1✔
1276
                    }
1277
                }
1✔
1278
            }
1279
        }
1✔
1280
    }
1✔
1281
    
1282
    private static void writeSeriesElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1283
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1284
            String key = entry.getKey();
1✔
1285
            MetadataBlockDTO value = entry.getValue();
1✔
1286
            if ("citation".equals(key)) {               
1✔
1287
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1288
                    if (DatasetFieldConstant.series.equals(fieldDTO.getTypeName())) {
1✔
1289
                        String seriesName = "";
1✔
1290
                        String seriesInformation = "";
1✔
1291
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1292
                            xmlw.writeStartElement("serStmt");
1✔
1293
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1294
                                FieldDTO next = iterator.next();
1✔
1295
                                if (DatasetFieldConstant.seriesName.equals(next.getTypeName())) {
1✔
1296
                                    seriesName = next.getSinglePrimitive();
1✔
1297
                                }
1298
                                if (DatasetFieldConstant.seriesInformation.equals(next.getTypeName())) {
1✔
1299
                                    seriesInformation = next.getSinglePrimitive();
1✔
1300
                                }
1301
                            }
1✔
1302
                            if (!seriesName.isEmpty()) {
1✔
1303
                                xmlw.writeStartElement("serName");
1✔
1304
                                xmlw.writeCharacters(seriesName);
1✔
1305
                                xmlw.writeEndElement(); //serName
1✔
1306
                            }
1307
                            if (!seriesInformation.isEmpty()) {
1✔
1308
                                xmlw.writeStartElement("serInfo");
1✔
1309
                                xmlw.writeCharacters(seriesInformation);
1✔
1310
                                xmlw.writeEndElement(); //serInfo
1✔
1311
                            }
1312
                            xmlw.writeEndElement(); //serStmt
1✔
1313
                        }
1✔
1314
                    }
1315
                }
1✔
1316
            }
1317
        }
1✔
1318
    }
1✔
1319
    
1320
    private static void writeTargetSampleElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1321
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1322
            String key = entry.getKey();
1✔
1323
            MetadataBlockDTO value = entry.getValue();
1✔
1324
            if ("socialscience".equals(key)) {
1✔
1325
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1326
                    if (DatasetFieldConstant.targetSampleSize.equals(fieldDTO.getTypeName())) {
1✔
1327
                        xmlw.writeStartElement("targetSampleSize");
1✔
1328
                        String sizeFormula = "";
1✔
1329
                        String actualSize = "";
1✔
1330
                        Set<FieldDTO> foo = fieldDTO.getSingleCompound();
1✔
1331
                        for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1332
                            FieldDTO next = iterator.next();
1✔
1333
                            if (DatasetFieldConstant.targetSampleSizeFormula.equals(next.getTypeName())) {
1✔
1334
                                sizeFormula = next.getSinglePrimitive();
1✔
1335
                            }
1336
                            if (DatasetFieldConstant.targetSampleActualSize.equals(next.getTypeName())) {
1✔
1337
                                actualSize = next.getSinglePrimitive();
1✔
1338
                            }
1339
                        }
1✔
1340
                        /* <sampleSize> must come before <sampleSizeFormula>! -L.A. */
1341
                        if (!actualSize.isEmpty()) {
1✔
1342
                            xmlw.writeStartElement("sampleSize");
1✔
1343
                            xmlw.writeCharacters(actualSize);
1✔
1344
                            xmlw.writeEndElement(); //sampleSize
1✔
1345
                        }
1346
                        if (!sizeFormula.isEmpty()) {
1✔
1347
                            xmlw.writeStartElement("sampleSizeFormula");
1✔
1348
                            xmlw.writeCharacters(sizeFormula);
1✔
1349
                            xmlw.writeEndElement(); //sampleSizeFormula
1✔
1350
                        }
1351
                        
1352
                        xmlw.writeEndElement(); // targetSampleSize
1✔
1353
                    }
1354
                }
1✔
1355
            }
1356
        }
1✔
1357
    }
1✔
1358
    
1359
    private static void writeNotesElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1360
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1361
            String key = entry.getKey();
1✔
1362
            MetadataBlockDTO value = entry.getValue();
1✔
1363
            if ("socialscience".equals(key)) {
1✔
1364
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1365
                    if (DatasetFieldConstant.socialScienceNotes.equals(fieldDTO.getTypeName())) {
1✔
1366
                        String notesText = "";
1✔
1367
                        String notesType = "";
1✔
1368
                        String notesSubject= "";
1✔
1369
                        Set<FieldDTO> foo = fieldDTO.getSingleCompound();
1✔
1370
                        for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1371
                            FieldDTO next = iterator.next();
1✔
1372
                            if (DatasetFieldConstant.socialScienceNotesText.equals(next.getTypeName())) {
1✔
1373
                                notesText = next.getSinglePrimitive();
1✔
1374
                            }
1375
                            if (DatasetFieldConstant.socialScienceNotesType.equals(next.getTypeName())) {
1✔
1376
                                notesType = next.getSinglePrimitive();
1✔
1377
                            }
1378
                            if (DatasetFieldConstant.socialScienceNotesSubject.equals(next.getTypeName())) {
1✔
1379
                                notesSubject = next.getSinglePrimitive();
1✔
1380
                            }
1381
                        }
1✔
1382
                        if (!notesText.isEmpty()) {
1✔
1383
                            xmlw.writeStartElement("notes");
1✔
1384
                            XmlWriterUtil.writeAttribute(xmlw,"type",notesType);
1✔
1385
                            XmlWriterUtil.writeAttribute(xmlw,"subject",notesSubject);
1✔
1386
                            xmlw.writeCharacters(notesText);
1✔
1387
                            xmlw.writeEndElement(); 
1✔
1388
                        }
1389
                    }
1390
                }
1✔
1391
            }
1392
        }
1✔
1393
    }
1✔
1394
    
1395
    // TODO: 
1396
    // see if there's more information that we could encode in this otherMat. 
1397
    // contentType? Unfs and such? (in the "short" DDI that is being used for 
1398
    // harvesting *all* files are encoded as otherMats; even tabular ones.
1399
    private static void createOtherMats(XMLStreamWriter xmlw, List<FileDTO> fileDtos) throws XMLStreamException {
1400
        // The preferred URL for this dataverse, for cooking up the file access API links:
1401
        String dataverseUrl = SystemConfig.getDataverseSiteUrlStatic();
1✔
1402
        
1403
        for (FileDTO fileDTo : fileDtos) {
1✔
1404
            // We'll continue using the scheme we've used before, in DVN2-3: non-tabular files are put into otherMat,
1405
            // tabular ones - in fileDscr sections. (fileDscr sections have special fields for numbers of variables
1406
            // and observations, etc.)
1407
            if (fileDTo.getDataFile().getDataTables() == null || fileDTo.getDataFile().getDataTables().isEmpty()) {
1✔
1408
                xmlw.writeStartElement("otherMat");
1✔
1409
                XmlWriterUtil.writeAttribute(xmlw, "ID", "f" + fileDTo.getDataFile().getId());
1✔
1410
                String pidURL = fileDTo.getDataFile().getPidURL();
1✔
1411
                if (pidURL != null && !pidURL.isEmpty()){
1✔
1412
                    xmlw.writeAttribute("URI", pidURL);
×
1413
                } else {
1414
                    xmlw.writeAttribute("URI", dataverseUrl + "/api/access/datafile/" + fileDTo.getDataFile().getId());
1✔
1415
                }
1416
                xmlw.writeAttribute("level", "datafile");
1✔
1417
                xmlw.writeStartElement("labl");
1✔
1418
                xmlw.writeCharacters(fileDTo.getDataFile().getFilename());
1✔
1419
                xmlw.writeEndElement(); // labl
1✔
1420
                writeFileDescription(xmlw, fileDTo);
1✔
1421
                // there's no readily available field in the othermat section 
1422
                // for the content type (aka mime type); so we'll store it in this
1423
                // specially formatted notes section:
1424
                String contentType = fileDTo.getDataFile().getContentType();
1✔
1425
                if (!StringUtilisEmpty(contentType)) {
1✔
1426
                    xmlw.writeStartElement("notes");
1✔
1427
                    xmlw.writeAttribute("level", LEVEL_FILE);
1✔
1428
                    xmlw.writeAttribute("type", NOTE_TYPE_CONTENTTYPE);
1✔
1429
                    xmlw.writeAttribute("subject", NOTE_SUBJECT_CONTENTTYPE);
1✔
1430
                    xmlw.writeCharacters(contentType);
1✔
1431
                    xmlw.writeEndElement(); // notes
1✔
1432
                }
1433
                xmlw.writeEndElement(); // otherMat
1✔
1434
            }
1435
        }
1✔
1436
    }
1✔
1437
    
1438
    // An alternative version of the createOtherMats method - this one is used 
1439
    // when a "full" DDI is being cooked; just like the fileDscr and data/var sections methods, 
1440
    // it operates on the list of FileMetadata entities, not on File DTOs. This is because
1441
    // DTOs do not support "tabular", variable-level metadata yet. And we need to be able to 
1442
    // tell if this file is in fact tabular data - so that we know if it needs an
1443
    // otherMat, or a fileDscr section. 
1444
    // -- L.A. 4.5 
1445
    
1446
    private static void createOtherMatsFromFileMetadatas(XMLStreamWriter xmlw, JsonArray fileDetails) throws XMLStreamException {
1447
        // The preferred URL for this dataverse, for cooking up the file access API links:
1448
        String dataverseUrl = SystemConfig.getDataverseSiteUrlStatic();
1✔
1449
        
1450
        for (int i=0;i<fileDetails.size();i++) {
1✔
1451
            JsonObject fileJson = fileDetails.getJsonObject(i);
×
1452
            // We'll continue using the scheme we've used before, in DVN2-3: non-tabular files are put into otherMat,
1453
            // tabular ones - in fileDscr sections. (fileDscr sections have special fields for numbers of variables
1454
            // and observations, etc.)
1455
            if (!fileJson.containsKey("dataTables")) {
×
1456
                xmlw.writeStartElement("otherMat");
×
1457
                xmlw.writeAttribute("ID", "f" + fileJson.getJsonNumber(("id").toString()));
×
1458
                if (fileJson.containsKey("pidUrl")){
×
NEW
1459
                    XmlWriterUtil.writeAttribute(xmlw, "URI",  fileJson.getString("pidUrl"));
×
1460
                }  else {
NEW
1461
                    xmlw.writeAttribute("URI", dataverseUrl + "/api/access/datafile/" + fileJson.getJsonNumber("id").toString());
×
1462
                }
1463

1464
                xmlw.writeAttribute("level", "datafile");
×
1465
                xmlw.writeStartElement("labl");
×
1466
                xmlw.writeCharacters(fileJson.getString("filename"));
×
1467
                xmlw.writeEndElement(); // labl
×
1468
                
1469
                if (fileJson.containsKey("description")) {
×
1470
                    xmlw.writeStartElement("txt");
×
1471
                    xmlw.writeCharacters(fileJson.getString("description"));
×
1472
                    xmlw.writeEndElement(); // txt
×
1473
                }
1474
                // there's no readily available field in the othermat section 
1475
                // for the content type (aka mime type); so we'll store it in this
1476
                // specially formatted notes section:
1477
                if (fileJson.containsKey("contentType")) {
×
1478
                    xmlw.writeStartElement("notes");
×
1479
                    xmlw.writeAttribute("level", LEVEL_FILE);
×
1480
                    xmlw.writeAttribute("type", NOTE_TYPE_CONTENTTYPE);
×
1481
                    xmlw.writeAttribute("subject", NOTE_SUBJECT_CONTENTTYPE);
×
1482
                    xmlw.writeCharacters(fileJson.getString("contentType"));
×
1483
                    xmlw.writeEndElement(); // notes
×
1484
                }
1485
                xmlw.writeEndElement(); // otherMat
×
1486
            }
1487
        }
1488
    }
1✔
1489
    
1490
    private static void writeFileDescription(XMLStreamWriter xmlw, FileDTO fileDTo) throws XMLStreamException {
1491
        xmlw.writeStartElement("txt");
1✔
1492
        String description = fileDTo.getDataFile().getDescription();
1✔
1493
        if (description != null) {
1✔
1494
            xmlw.writeCharacters(description);
1✔
1495
        }
1496
        xmlw.writeEndElement(); // txt
1✔
1497
    }
1✔
1498
    
1499

1500
    
1501
    private static List<String> dto2PrimitiveList(DatasetVersionDTO datasetVersionDTO, String datasetFieldTypeName) {
1502
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1503
            MetadataBlockDTO value = entry.getValue();
1✔
1504
            for (FieldDTO fieldDTO : value.getFields()) {
1✔
1505
                if (datasetFieldTypeName.equals(fieldDTO.getTypeName())) {
1✔
1506
                    // This hack is here to make sure the export does not blow 
1507
                    // up on an instance that upgraded to a Dataverse version
1508
                    // where a certain primitive has been made multiple, but has
1509
                    // not yet update the block. 
1510
                    if (fieldDTO.getMultiple() != null && fieldDTO.getMultiple()) {
1✔
1511
                        return fieldDTO.getMultiplePrimitive();
1✔
1512
                    } else {
1513
                        return Arrays.asList(fieldDTO.getSinglePrimitive());
×
1514
                    }
1515
                }
1516
            }
1✔
1517
        }
1✔
1518
        return null;
1✔
1519
    }
1520
    
1521
    private static FieldDTO dto2FieldDTO(DatasetVersionDTO datasetVersionDTO, String datasetFieldTypeName, String metadataBlockName) {
1522
        MetadataBlockDTO block = datasetVersionDTO.getMetadataBlocks().get(metadataBlockName);
1✔
1523
        if (block != null) {
1✔
1524
            for (FieldDTO fieldDTO : block.getFields()) {
1✔
1525
                if (datasetFieldTypeName.equals(fieldDTO.getTypeName())) {
1✔
1526
                    return fieldDTO;
1✔
1527
                }
1528
            }
1✔
1529
        }
1530
        return null;
1✔
1531
    }
1532

1533

1534
    private static boolean StringUtilisEmpty(String str) {
1535
        if (str == null || str.trim().equals("")) {
1✔
1536
            return true;
×
1537
        }
1538
        return false;
1✔
1539
    }
1540

1541
    private static void saveJsonToDisk(String datasetVersionAsJson) throws IOException {
1542
        Files.write(Paths.get("/tmp/out.json"), datasetVersionAsJson.getBytes());
×
1543
    }
×
1544
    
1545
    
1546
    
1547
    
1548
    // Methods specific to the tabular data ("<dataDscr>") section. 
1549
    // Note that these do NOT operate on DTO objects, but instead directly 
1550
    // on Dataverse DataVariable, DataTable, etc. objects. 
1551
    // This is because for this release (4.5) we are recycling the already available 
1552
    // code, and this is what we got. (We already have DTO objects for DataTable, 
1553
    // and DataVariable, etc., but the current version JsonPrinter.jsonAsDatasetDto() 
1554
    // does not produce JSON for these objects - it stops at DataFile. Eventually 
1555
    // we want all of our objects to be exportable as JSON, and then all the exports
1556
    // can go through the same DTO state... But we don't have time for it now; 
1557
    // plus, the structure of file-level metadata is currently being re-designed, 
1558
    // so we probably should not invest any time into it right now). -- L.A. 4.5
1559
    
1560
    public static void createDataDscr(XMLStreamWriter xmlw, JsonArray fileDetails) throws XMLStreamException {
1561

1562
        if (fileDetails.isEmpty()) {
1✔
1563
            return;
1✔
1564
        }
1565

1566
        boolean tabularData = false;
×
1567

1568
        // we're not writing the opening <dataDscr> tag until we find an actual 
1569
        // tabular datafile.
1570
        for (int i=0;i<fileDetails.size();i++) {
×
1571
            JsonObject fileJson = fileDetails.getJsonObject(i);
×
1572

1573
            /**
1574
             * Previously (in Dataverse 5.3 and below) the dataDscr section was
1575
             * included for restricted files but that meant that summary
1576
             * statistics were exposed. (To get at these statistics, API users
1577
             * should instead use the "Data Variable Metadata Access" endpoint.)
1578
             * These days we skip restricted files to avoid this exposure.
1579
             */
1580
            if (fileJson.containsKey("restricted") && fileJson.getBoolean("restricted")) {
×
1581
                continue;
×
1582
            }
1583
            if(fileJson.containsKey("embargo")) {
×
1584
             String dateString = fileJson.getJsonObject("embargo").getString("dateAvailable");
×
1585
             LocalDate endDate = LocalDate.parse(dateString);
×
1586
             if (endDate != null && endDate.isAfter(LocalDate.now())) {
×
1587
                 //Embargo is active so skip
1588
                 continue;
×
1589
             }
1590
            }
1591
        
1592
            if (fileJson.containsKey("dataTables")) {
×
1593
                if (!tabularData) {
×
1594
                    xmlw.writeStartElement("dataDscr");
×
1595
                    tabularData = true;
×
1596
                }
1597
                if(fileJson.containsKey("varGroups")) {
×
1598
                    JsonArray varGroups = fileJson.getJsonArray("varGroups");
×
1599
                    for (int j=0;j<varGroups.size();j++){
×
1600
                        createVarGroupDDI(xmlw, varGroups.getJsonObject(j));
×
1601
                    }
1602
                }
1603
                JsonObject dataTable = fileJson.getJsonArray("dataTables").getJsonObject(0);
×
1604
                JsonArray vars = dataTable.getJsonArray("dataVariables");
×
1605
                if (vars != null) {
×
1606
                    for (int j = 0; j < vars.size(); j++) {
×
1607
                        createVarDDI(xmlw, vars.getJsonObject(j), fileJson.getJsonNumber("id").toString(),
×
1608
                                fileJson.getJsonNumber("fileMetadataId").toString());
×
1609
                    }
1610
                }
1611
            }
1612
        }
1613

1614
        if (tabularData) {
×
1615
            xmlw.writeEndElement(); // dataDscr
×
1616
        }
1617
    }
×
1618
    private static void createVarGroupDDI(XMLStreamWriter xmlw, JsonObject varGrp) throws XMLStreamException {
1619
        xmlw.writeStartElement("varGrp");
×
1620
        xmlw.writeAttribute("ID", "VG" + varGrp.getJsonNumber("id").toString());
×
1621
        String vars = "";
×
1622
        JsonArray varsInGroup = varGrp.getJsonArray("dataVariableIds");
×
1623
        for (int j=0;j<varsInGroup.size();j++){
×
1624
            vars = vars + " v" + varsInGroup.getString(j);
×
1625
        }
1626
        vars = vars.trim();
×
1627
        XmlWriterUtil.writeAttribute(xmlw, "var", vars );
×
1628

1629

1630
        if (varGrp.containsKey("label")) {
×
1631
            xmlw.writeStartElement("labl");
×
1632
            xmlw.writeCharacters(varGrp.getString("label"));
×
1633
            xmlw.writeEndElement(); // group label (labl)
×
1634
        }
1635

1636
        xmlw.writeEndElement(); //varGrp
×
1637
    }
×
1638
    
1639
    private static void createVarDDI(XMLStreamWriter xmlw, JsonObject dvar, String fileId, String fileMetadataId) throws XMLStreamException {
1640
        xmlw.writeStartElement("var");
×
1641
        xmlw.writeAttribute("ID", "v" + dvar.getJsonNumber("id").toString());
×
1642
        XmlWriterUtil.writeAttribute(xmlw, "name", dvar.getString("name"));
×
1643

1644
        JsonObject vm = null;
×
1645
        JsonArray vmArray = dvar.getJsonArray("variableMetadata"); 
×
1646
        for (int i=0;i< vmArray.size();i++) {
×
1647
            JsonObject curVm =vmArray.getJsonObject(i); 
×
1648
            if (curVm.containsKey("fileMetadataId") && curVm.getString("fileMetadataId").equals(fileMetadataId) ){
×
1649
                vm = curVm;
×
1650
                break;
×
1651
            }
1652
        }
1653

1654
        if (dvar.containsKey("numberOfDecimalPoints")) {
×
1655
            XmlWriterUtil.writeAttribute(xmlw, "dcml", dvar.getJsonNumber("numberOfDecimalPoints").toString());
×
1656
        }
1657

1658
        if (dvar.getBoolean("isOrderedCategorical")) {
×
1659
            xmlw.writeAttribute("nature", "ordinal");
×
1660
        }
1661

1662
        if (dvar.containsKey("variableIntervalType")) {
×
1663
            XmlWriterUtil.writeAttribute(xmlw, "intrvl", dvar.getString("variableIntervalType"));
×
1664
        }
1665

1666
        if (vm != null) {
×
1667
            if (vm.getBoolean("isWeightvar")) {
×
1668
                xmlw.writeAttribute("wgt", "wgt");
×
1669
            }
1670
            if (vm.containsKey("isWeighted") && vm.containsKey("weightVariableId")) {
×
1671
                xmlw.writeAttribute("wgt-var", "v"+vm.getString("weightVariableId"));
×
1672
            }
1673
        }
1674

1675
        // location
1676
        xmlw.writeEmptyElement("location");
×
1677
        if (dvar.containsKey("fileStartPosition")) {
×
1678
            XmlWriterUtil.writeAttribute(xmlw, "StartPos", dvar.getJsonNumber("fileStartPosition").toString());
×
1679
        }
1680
        if (dvar.containsKey("fileEndPosition")) {
×
1681
            XmlWriterUtil.writeAttribute(xmlw, "EndPos", dvar.getJsonNumber("fileEndPosition").toString());
×
1682
        }
1683
        if (dvar.containsKey("recordSegmentNumber")) {
×
1684
            XmlWriterUtil.writeAttribute(xmlw, "RecSegNo", dvar.getJsonNumber("recordSegmentNumber").toString());
×
1685
        }
1686

1687
        xmlw.writeAttribute("fileid", "f" + fileId);
×
1688

1689
        // labl
1690
        if ((vm == null || !vm.containsKey("label"))) {
×
1691
            if(dvar.containsKey("label")) {
×
1692
                xmlw.writeStartElement("labl");
×
1693
                xmlw.writeAttribute("level", "variable");
×
1694
                xmlw.writeCharacters(dvar.getString("label"));
×
1695
                xmlw.writeEndElement(); //labl
×
1696
            }
1697
        } else {
1698
            xmlw.writeStartElement("labl");
×
1699
            xmlw.writeAttribute("level", "variable");
×
1700
            xmlw.writeCharacters(vm.getString("label"));
×
1701
            xmlw.writeEndElement(); //labl
×
1702
        }
1703

1704
        if (vm != null) {
×
1705
            if (vm.containsKey("literalQuestion") || vm.containsKey("interviewInstruction") || vm.containsKey("postQuestion")) {
×
1706
                xmlw.writeStartElement("qstn");
×
1707
                if (vm.containsKey("literalQuestion")) {
×
1708
                    xmlw.writeStartElement("qstnLit");
×
1709
                    xmlw.writeCharacters(vm.getString("literalQuestion"));
×
1710
                    xmlw.writeEndElement(); // qstnLit
×
1711
                }
1712
                if (vm.containsKey("interviewInstruction")) {
×
1713
                    xmlw.writeStartElement("ivuInstr");
×
1714
                    xmlw.writeCharacters(vm.getString("interviewInstruction"));
×
1715
                    xmlw.writeEndElement(); //ivuInstr
×
1716
                }
1717
                if (vm.containsKey("postQuestion")) {
×
1718
                    xmlw.writeStartElement("postQTxt");
×
1719
                    xmlw.writeCharacters(vm.getString("postQuestion"));
×
1720
                    xmlw.writeEndElement(); //ivuInstr
×
1721
                }
1722
                xmlw.writeEndElement(); //qstn
×
1723
            }
1724
        }
1725

1726
        // invalrng
1727
        if (dvar.containsKey("invalidRanges")) {
×
1728
            boolean invalrngAdded = false;
×
1729
            JsonArray ranges = dvar.getJsonArray("invalidRanges");
×
1730
            for (int i = 0; i < ranges.size(); i++) {
×
1731
                JsonObject range = ranges.getJsonObject(0);
×
1732
                // if (range.getBeginValueType() != null &&
1733
                // range.getBeginValueType().getName().equals(DB_VAR_RANGE_TYPE_POINT)) {
1734
                if (range.getBoolean("hasBeginValueType") && range.getBoolean("isBeginValueTypePoint")) {
×
1735
                    if (range.containsKey("beginValue")) {
×
1736
                        invalrngAdded = XmlWriterUtil.writeOpenTagIfNeeded(xmlw, "invalrng", invalrngAdded);
×
1737
                        xmlw.writeEmptyElement("item");
×
1738
                        XmlWriterUtil.writeAttribute(xmlw, "VALUE", range.getString("beginValue"));
×
1739
                    }
1740
                } else {
1741
                    invalrngAdded = XmlWriterUtil.writeOpenTagIfNeeded(xmlw, "invalrng", invalrngAdded);
×
1742
                    xmlw.writeEmptyElement("range");
×
1743
                    if (range.getBoolean("hasBeginValueType") && range.containsKey("beginValue")) {
×
1744
                        if (range.getBoolean("isBeginValueTypeMin")) {
×
1745
                            XmlWriterUtil.writeAttribute(xmlw, "min", range.getString("beginValue"));
×
1746
                        } else if (range.getBoolean("isBeginValueTypeMinExcl")) {
×
1747
                            XmlWriterUtil.writeAttribute(xmlw, "minExclusive", range.getString("beginValue"));
×
1748
                        }
1749
                    }
1750
                    if (range.getBoolean("hasEndValueType") && range.containsKey("endValue")) {
×
1751
                        if (range.getBoolean("isEndValueTypeMax")) {
×
1752
                            XmlWriterUtil.writeAttribute(xmlw, "max", range.getString("endValue"));
×
1753
                        } else if (range.getBoolean("isEndValueTypeMaxExcl")) {
×
1754
                            XmlWriterUtil.writeAttribute(xmlw, "maxExclusive", range.getString("endValue"));
×
1755
                        }
1756
                    }
1757
                }
1758
            }
1759
            if (invalrngAdded) {
×
1760
                xmlw.writeEndElement(); // invalrng
×
1761
            }
1762
        }
1763

1764
        //universe
1765
        if (vm != null) {
×
1766
            if (vm.containsKey("universe")) {
×
1767
                xmlw.writeStartElement("universe");
×
1768
                xmlw.writeCharacters(vm.getString("universe"));
×
1769
                xmlw.writeEndElement(); //universe
×
1770
            }
1771
        }
1772

1773
        // sum stats
1774
        if (dvar.containsKey("summaryStatistics")) {
×
1775
            for (Entry<String, JsonValue> sumStat : dvar.getJsonObject("summaryStatistics").entrySet()) {
×
1776
                xmlw.writeStartElement("sumStat");
×
1777
                XmlWriterUtil.writeAttribute(xmlw, "type", sumStat.getKey());
×
1778
                xmlw.writeCharacters(((JsonString)sumStat.getValue()).getString());
×
1779
                xmlw.writeEndElement(); // sumStat
×
1780
            }
×
1781
        }
1782

1783
        // categories
1784
        if (dvar.containsKey("variableCategories")) {
×
1785
            JsonArray varCats = dvar.getJsonArray("variableCategories");
×
1786
            for (int i = 0; i < varCats.size(); i++) {
×
1787
                JsonObject varCat = varCats.getJsonObject(i);
×
1788
                xmlw.writeStartElement("catgry");
×
1789
                if (varCat.getBoolean("isMissing")) {
×
1790
                    xmlw.writeAttribute("missing", "Y");
×
1791
                }
1792

1793
                // catValu
1794
                xmlw.writeStartElement("catValu");
×
1795
                xmlw.writeCharacters(varCat.getString("value"));
×
1796
                xmlw.writeEndElement(); // catValu
×
1797

1798
                // label
1799
                if (varCat.containsKey("label")) {
×
1800
                    xmlw.writeStartElement("labl");
×
1801
                    xmlw.writeAttribute("level", "category");
×
1802
                    xmlw.writeCharacters(varCat.getString("label"));
×
1803
                    xmlw.writeEndElement(); // labl
×
1804
                }
1805

1806
                // catStat
1807
                if (varCat.containsKey("frequency")) {
×
1808
                    xmlw.writeStartElement("catStat");
×
1809
                    xmlw.writeAttribute("type", "freq");
×
1810
                    Double freq = varCat.getJsonNumber("frequency").doubleValue();
×
1811
                    // if frequency is actually a long value, we want to write "100" instead of
1812
                    // "100.0"
1813
                    if (Math.floor(freq) == freq) {
×
1814
                        xmlw.writeCharacters(Long.valueOf(freq.longValue()).toString());
×
1815
                    } else {
1816
                        xmlw.writeCharacters(freq.toString());
×
1817
                    }
1818
                    xmlw.writeEndElement(); // catStat
×
1819
                }
1820

1821
                // catStat weighted freq
1822
                if (vm != null && vm.getBoolean("isWeighted")) {
×
1823
                    JsonArray catMetas = vm.getJsonArray("categoryMetadatas");
×
1824
                    for (int j = 0; i < catMetas.size(); j++) {
×
1825
                        JsonObject cm = catMetas.getJsonObject(j);
×
1826
                        if (cm.getString("categoryValue").equals(varCat.getString("value"))) {
×
1827
                            xmlw.writeStartElement("catStat");
×
1828
                            xmlw.writeAttribute("wgtd", "wgtd");
×
1829
                            xmlw.writeAttribute("type", "freq");
×
1830
                            xmlw.writeCharacters(cm.getJsonNumber("wFreq").toString());
×
1831
                            xmlw.writeEndElement(); // catStat
×
1832
                            break;
×
1833
                        }
1834
                    }
1835
                }
1836

1837
                xmlw.writeEndElement(); // catgry
×
1838
            }
1839
        }
1840

1841

1842
        // varFormat
1843
        xmlw.writeEmptyElement("varFormat");
×
1844
        if(dvar.containsKey("variableFormatType")) {
×
1845
            XmlWriterUtil.writeAttribute(xmlw, "type", dvar.getString("variableFormatType").toLowerCase());
×
1846
        } else {
1847
            throw new XMLStreamException("Illegal Variable Format Type!");
×
1848
        }
1849
        if(dvar.containsKey("format")) {
×
1850
            XmlWriterUtil.writeAttribute(xmlw, "formatname", dvar.getString("format"));
×
1851
        }
1852
        //experiment writeAttribute(xmlw, "schema", dv.getFormatSchema());
1853
        if(dvar.containsKey("formatCategory")) {
×
1854
            XmlWriterUtil.writeAttribute(xmlw, "category", dvar.getString("formatCategory"));
×
1855
        }
1856

1857
        // notes
1858
        if (dvar.containsKey("UNF") && !dvar.getString("UNF").isBlank()) {
×
1859
            xmlw.writeStartElement("notes");
×
1860
            xmlw.writeAttribute("subject", "Universal Numeric Fingerprint");
×
1861
            xmlw.writeAttribute("level", "variable");
×
1862
            xmlw.writeAttribute("type", "Dataverse:UNF");
×
1863
            xmlw.writeCharacters(dvar.getString("UNF"));
×
1864
            xmlw.writeEndElement(); //notes
×
1865
        }
1866

1867
        if (vm != null) {
×
1868
            if (vm.containsKey("notes")) {
×
1869
                xmlw.writeStartElement("notes");
×
1870
                xmlw.writeCData(vm.getString("notes"));
×
1871
                xmlw.writeEndElement(); //notes CDATA
×
1872
            }
1873
        }
1874

1875

1876

1877
        xmlw.writeEndElement(); //var
×
1878

1879
    }
×
1880
    
1881
    private static void createFileDscr(XMLStreamWriter xmlw, JsonArray fileDetails) throws XMLStreamException {
1882
        String dataverseUrl = SystemConfig.getDataverseSiteUrlStatic();
1✔
1883
        for (int i =0;i<fileDetails.size();i++) {
1✔
1884
            JsonObject fileJson = fileDetails.getJsonObject(i);
×
1885
            //originalFileFormat is one of several keys that only exist for tabular data
1886
            if (fileJson.containsKey("originalFileFormat")) {
×
1887
                JsonObject dt = null;
×
1888
                if (fileJson.containsKey("dataTables")) {
×
1889
                    dt = fileJson.getJsonArray("dataTables").getJsonObject(0);
×
1890
                }
1891
                xmlw.writeStartElement("fileDscr");
×
1892
                String fileId = fileJson.getJsonNumber("id").toString();
×
1893
                xmlw.writeAttribute("ID", "f" + fileId);
×
1894
                xmlw.writeAttribute("URI", dataverseUrl + "/api/access/datafile/" + fileId);
×
1895

1896
                xmlw.writeStartElement("fileTxt");
×
1897
                xmlw.writeStartElement("fileName");
×
1898
                xmlw.writeCharacters(fileJson.getString("filename"));
×
1899
                xmlw.writeEndElement(); // fileName
×
1900

1901
                if (dt != null && (dt.containsKey("caseQuantity") || dt.containsKey("varQuantity")
×
1902
                        || dt.containsKey("recordsPerCase"))) {
×
1903
                    xmlw.writeStartElement("dimensns");
×
1904

1905
                    if (dt.containsKey("caseQuantity")) {
×
1906
                        xmlw.writeStartElement("caseQnty");
×
1907
                        xmlw.writeCharacters(dt.getJsonNumber("caseQuantity").toString());
×
1908
                        xmlw.writeEndElement(); // caseQnty
×
1909
                    }
1910

1911
                    if (dt.containsKey("varQuantity")) {
×
1912
                        xmlw.writeStartElement("varQnty");
×
1913
                        xmlw.writeCharacters(dt.getJsonNumber("varQuantity").toString());
×
1914
                        xmlw.writeEndElement(); // varQnty
×
1915
                    }
1916

1917
                    if (dt.containsKey("recordsPerCase")) {
×
1918
                        xmlw.writeStartElement("recPrCas");
×
1919
                        xmlw.writeCharacters(dt.getJsonNumber("recordsPerCase").toString());
×
1920
                        xmlw.writeEndElement(); // recPrCas
×
1921
                    }
1922

1923
                    xmlw.writeEndElement(); // dimensns
×
1924
                }
1925

1926
                xmlw.writeStartElement("fileType");
×
1927
                xmlw.writeCharacters(fileJson.getString("contentType"));
×
1928
                xmlw.writeEndElement(); // fileType
×
1929

1930
                xmlw.writeEndElement(); // fileTxt
×
1931

1932
                // various notes:
1933
                // this specially formatted note section is used to store the UNF
1934
                // (Universal Numeric Fingerprint) signature:
1935
                if ((dt!=null) && (dt.containsKey("UNF") && !dt.getString("UNF").isBlank())) {
×
1936
                    xmlw.writeStartElement("notes");
×
1937
                    xmlw.writeAttribute("level", LEVEL_FILE);
×
1938
                    xmlw.writeAttribute("type", NOTE_TYPE_UNF);
×
1939
                    xmlw.writeAttribute("subject", NOTE_SUBJECT_UNF);
×
1940
                    xmlw.writeCharacters(dt.getString("UNF"));
×
1941
                    xmlw.writeEndElement(); // notes
×
1942
                }
1943

1944
                // If any tabular tags are present, each is formatted in a 
1945
                // dedicated note:
1946
                if (fileJson.containsKey("tabularTags")) {
×
1947
                    JsonArray tags = fileJson.getJsonArray("tabularTags");
×
1948
                    for (int j = 0; j < tags.size(); j++) {
×
1949
                        xmlw.writeStartElement("notes");
×
1950
                        xmlw.writeAttribute("level", LEVEL_FILE);
×
1951
                        xmlw.writeAttribute("type", NOTE_TYPE_TAG);
×
1952
                        xmlw.writeAttribute("subject", NOTE_SUBJECT_TAG);
×
1953
                        xmlw.writeCharacters(tags.getString(j));
×
1954
                        xmlw.writeEndElement(); // notes
×
1955
                    }
1956
                }
1957
                
1958
                // Adding a dedicated node for the description entry (for 
1959
                // non-tabular files we format it under the <txt> field)
1960
                if (fileJson.containsKey("description")) {
×
1961
                    xmlw.writeStartElement("notes");
×
1962
                    xmlw.writeAttribute("level", LEVEL_FILE);
×
1963
                    xmlw.writeAttribute("type", NOTE_TYPE_FILEDESCRIPTION);
×
1964
                    xmlw.writeAttribute("subject", NOTE_SUBJECT_FILEDESCRIPTION);
×
1965
                    xmlw.writeCharacters(fileJson.getString("description"));
×
1966
                    xmlw.writeEndElement(); // notes
×
1967
                }
1968

1969
                // TODO: add the remaining fileDscr elements!
1970
                xmlw.writeEndElement(); // fileDscr
×
1971
            }
1972
        }
1973
    }
1✔
1974
    
1975
    
1976

1977

1978

1979
    public static void datasetHtmlDDI(InputStream datafile, OutputStream outputStream) throws XMLStreamException {
1980
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1✔
1981

1982
        try {
1983
            Document document;
1984
            InputStream  styleSheetInput = DdiExportUtil.class.getClassLoader().getResourceAsStream("edu/harvard/iq/dataverse/codebook2-0.xsl");
1✔
1985

1986
            DocumentBuilder builder = factory.newDocumentBuilder();
1✔
1987
            document = builder.parse(datafile);
1✔
1988

1989
            // Use a Transformer for output
1990
            TransformerFactory tFactory = TransformerFactory.newInstance();
1✔
1991
            StreamSource stylesource = new StreamSource(styleSheetInput);
1✔
1992
            Transformer transformer = tFactory.newTransformer(stylesource);
1✔
1993

1994
            DOMSource source = new DOMSource(document);
1✔
1995
            StreamResult result = new StreamResult(outputStream);
1✔
1996
            transformer.transform(source, result);
1✔
1997
        } catch (TransformerConfigurationException tce) {
×
1998
            // Error generated by the parser
1999
            logger.severe("Transformer Factory error" + "   " + tce.getMessage());
×
2000
        } catch (TransformerException te) {
×
2001
            // Error generated by the parser
2002
            logger.severe("Transformation error" + "   " + te.getMessage());
×
2003

2004
        } catch (SAXException sxe) {
×
2005
            // Error generated by this application
2006
            // (or a parser-initialization error)
2007
            logger.severe("SAX error " + sxe.getMessage());
×
2008

2009
        } catch (ParserConfigurationException pce) {
×
2010
            // Parser with specified options can't be built
2011
            logger.severe("Parser configuration error " + pce.getMessage());
×
2012
        } catch (IOException ioe) {
×
2013
            // I/O error
2014
            logger.warning("I/O error " + ioe.getMessage());
×
2015
        }
1✔
2016

2017
    }
1✔
2018

2019
    public static void injectSettingsService(SettingsServiceBean settingsSvc) {
2020
        settingsService=settingsSvc;
1✔
2021
    }
1✔
2022

2023
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc