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

IQSS / dataverse / #23538

23 Oct 2024 04:54PM UTC coverage: 20.88% (+0.01%) from 20.87%
#23538

Pull #10790

github

web-flow
Merge 07e327ca6 into f970ab3f4
Pull Request #10790: fix: issues in exporters and citations for PermaLink/non-DOI PIDs

39 of 55 new or added lines in 7 files covered. (70.91%)

1 existing line in 1 file now uncovered.

17991 of 86162 relevant lines covered (20.88%)

0.21 hits per line

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

73.22
/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.DatasetDTO;
10
import edu.harvard.iq.dataverse.api.dto.DatasetVersionDTO;
11
import edu.harvard.iq.dataverse.api.dto.FieldDTO;
12
import edu.harvard.iq.dataverse.api.dto.FileDTO;
13
import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO;
14

15
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.LEVEL_FILE;
16
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_SUBJECT_TAG;
17
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_SUBJECT_UNF;
18
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_TYPE_TAG;
19
import static edu.harvard.iq.dataverse.export.DDIExportServiceBean.NOTE_TYPE_UNF;
20
import edu.harvard.iq.dataverse.export.DDIExporter;
21
import edu.harvard.iq.dataverse.pidproviders.PidUtil;
22
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
23

24

25
import edu.harvard.iq.dataverse.util.SystemConfig;
26
import edu.harvard.iq.dataverse.util.json.JsonUtil;
27
import edu.harvard.iq.dataverse.util.xml.XmlPrinter;
28
import edu.harvard.iq.dataverse.util.xml.XmlWriterUtil;
29

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

51
import javax.xml.parsers.DocumentBuilder;
52
import javax.xml.parsers.DocumentBuilderFactory;
53
import javax.xml.parsers.ParserConfigurationException;
54
import org.xml.sax.SAXException;
55
import org.w3c.dom.Document;
56
import org.apache.commons.lang3.StringUtils;
57

58
// For write operation
59
import javax.xml.transform.Transformer;
60
import javax.xml.transform.TransformerException;
61
import javax.xml.transform.TransformerFactory;
62
import javax.xml.transform.TransformerConfigurationException;
63
import javax.xml.transform.dom.DOMSource;
64
import javax.xml.transform.stream.StreamSource;
65
import javax.xml.transform.stream.StreamResult;
66
import java.io.InputStream;
67

68
public class DdiExportUtil {
×
69

70
    private static final Logger logger = Logger.getLogger(DdiExportUtil.class.getCanonicalName());
1✔
71
    public static final String NOTE_TYPE_TERMS_OF_USE = "DVN:TOU";
72
    public static final String NOTE_TYPE_TERMS_OF_ACCESS = "DVN:TOA";
73
    public static final String NOTE_TYPE_DATA_ACCESS_PLACE = "DVN:DAP";
74

75

76
    public static final String LEVEL_DV = "dv";
77

78
    
79
    static SettingsServiceBean settingsService;
80
    
81
    public static final String NOTE_TYPE_CONTENTTYPE = "DATAVERSE:CONTENTTYPE";
82
    public static final String NOTE_SUBJECT_CONTENTTYPE = "Content/MIME Type";
83
    public static final String CITATION_BLOCK_NAME = "citation";
84

85
    //Some tests don't send real PIDs that can be parsed
86
    //Use constant empty PID in these cases
87
    private static final String EMPTY_PID = "null:nullnullnull";
88

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

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

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

170
        String persistentAuthority = datasetDto.getAuthority();
1✔
171
        String persistentId = datasetDto.getIdentifier();
1✔
172

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

215
        writeAuthorsElement(xmlw, version);
1✔
216
        writeProducersElement(xmlw, version);
1✔
217
        
218
        xmlw.writeStartElement("distStmt");
1✔
219
      //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
220
        boolean distributorSet=false;
1✔
221
        MetadataBlockDTO citationDTO= version.getMetadataBlocks().get("citation");
1✔
222
        if(citationDTO!=null) {
1✔
223
            if(citationDTO.getField(DatasetFieldConstant.distributor)!=null) {
1✔
224
                distributorSet=true;
1✔
225
            }
226
        }
227
        
228
        boolean excludeRepository = settingsService.isTrueForKey(SettingsServiceBean.Key.ExportInstallationAsDistributorOnlyWhenNotSet, false);
1✔
229
        if (!StringUtils.isEmpty(datasetDto.getPublisher()) && !(excludeRepository && distributorSet)) {
1✔
230
            xmlw.writeStartElement("distrbtr");
1✔
231
            xmlw.writeAttribute("source", "archive");
1✔
232
            xmlw.writeCharacters(datasetDto.getPublisher());
1✔
233
            xmlw.writeEndElement(); //distrbtr
1✔
234
        }
235
        writeDistributorsElement(xmlw, version, datasetDto.getMetadataLanguage());
1✔
236
        writeContactsElement(xmlw, version);
1✔
237
        /* per SCHEMA, depositr comes before depDate! - L.A. */
238
        XmlWriterUtil.writeFullElement(xmlw, "depositr", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.depositor));
1✔
239
        /* ... and depDate comes before distDate - L.A. */
240
        XmlWriterUtil.writeFullElement(xmlw, "depDate", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.dateOfDeposit));
1✔
241
        XmlWriterUtil.writeFullElement(xmlw, "distDate", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.distributionDate));
1✔
242

243
        xmlw.writeEndElement(); // diststmt
1✔
244

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

264
        writeMethodElement(xmlw, version, datasetDto.getMetadataLanguage());
1✔
265
        writeDataAccess(xmlw , version);
1✔
266
        writeOtherStudyMaterial(xmlw , version);
1✔
267

268
        XmlWriterUtil.writeFullElement(xmlw, "notes", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.datasetLevelErrorNotes));
1✔
269
        
270
        xmlw.writeEndElement(); // stdyDscr
1✔
271

272
    }
1✔
273

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

294
    /*
295
            <xs:sequence>
296
               <xs:element ref="setAvail" minOccurs="0" maxOccurs="unbounded"/>
297
               <xs:element ref="useStmt" minOccurs="0" maxOccurs="unbounded"/>
298
               <xs:element ref="notes" minOccurs="0" maxOccurs="unbounded"/>
299
            </xs:sequence>
300
    */
301
    private static void writeDataAccess(XMLStreamWriter xmlw , DatasetVersionDTO version) throws XMLStreamException {
302
        xmlw.writeStartElement("dataAccs");
1✔
303
        
304
        xmlw.writeStartElement("setAvail");
1✔
305
        XmlWriterUtil.writeFullElement(xmlw, "accsPlac", version.getDataAccessPlace());
1✔
306
        XmlWriterUtil.writeFullElement(xmlw, "origArch", version.getOriginalArchive());
1✔
307
        XmlWriterUtil.writeFullElement(xmlw, "avlStatus", version.getAvailabilityStatus());
1✔
308
        XmlWriterUtil.writeFullElement(xmlw, "collSize", version.getSizeOfCollection());
1✔
309
        XmlWriterUtil.writeFullElement(xmlw, "complete", version.getStudyCompletion());
1✔
310
        xmlw.writeEndElement(); //setAvail
1✔
311
        
312
        xmlw.writeStartElement("useStmt");
1✔
313
        XmlWriterUtil.writeFullElement(xmlw, "confDec", version.getConfidentialityDeclaration());
1✔
314
        XmlWriterUtil.writeFullElement(xmlw, "specPerm", version.getSpecialPermissions());
1✔
315
        XmlWriterUtil.writeFullElement(xmlw, "restrctn", version.getRestrictions());
1✔
316
        XmlWriterUtil.writeFullElement(xmlw, "contact", version.getContactForAccess());
1✔
317
        XmlWriterUtil.writeFullElement(xmlw, "citReq", version.getCitationRequirements());
1✔
318
        XmlWriterUtil.writeFullElement(xmlw, "deposReq", version.getDepositorRequirements());
1✔
319
        XmlWriterUtil.writeFullElement(xmlw, "conditions", version.getConditions());
1✔
320
        XmlWriterUtil.writeFullElement(xmlw, "disclaimer", version.getDisclaimer());
1✔
321
        xmlw.writeEndElement(); //useStmt
1✔
322
        
323
        /* any <note>s: */
324
        if (version.getTermsOfAccess() != null && !version.getTermsOfAccess().trim().equals("")) {
1✔
325
            xmlw.writeStartElement("notes");
1✔
326
            xmlw.writeAttribute("type", NOTE_TYPE_TERMS_OF_ACCESS);
1✔
327
            xmlw.writeAttribute("level", LEVEL_DV);
1✔
328
            xmlw.writeCharacters(version.getTermsOfAccess());
1✔
329
            xmlw.writeEndElement(); //notes
1✔
330
        }
331
        xmlw.writeEndElement(); //dataAccs
1✔
332
    }
1✔
333
    
334
    private static void writeDocDescElement (XMLStreamWriter xmlw, DatasetDTO datasetDto) throws XMLStreamException {
335
        DatasetVersionDTO version = datasetDto.getDatasetVersion();
1✔
336
        String persistentProtocol = datasetDto.getProtocol();
1✔
337
        String persistentAgency = persistentProtocol;
1✔
338
        // The "persistentAgency" tag is used for the "agency" attribute of the 
339
        // <IDNo> ddi section; back in the DVN3 days we used "handle" and "DOI" 
340
        // for the 2 supported protocols, respectively. For the sake of backward
341
        // compatibility, we should probably stick with these labels: (-- L.A. 4.5)
342
        if ("hdl".equals(persistentAgency)) { 
1✔
343
            persistentAgency = "handle";
×
344
        } else if ("doi".equals(persistentAgency)) {
1✔
345
            persistentAgency = "DOI";
1✔
346
        }
347
        
348
        String persistentAuthority = datasetDto.getAuthority();
1✔
349
        String persistentId = datasetDto.getIdentifier();
1✔
350
        GlobalId pid = PidUtil.parseAsGlobalID(persistentProtocol, persistentAuthority, persistentId);
1✔
351
        String pidString;
352
        if(pid != null) {
1✔
353
            pidString = pid.asString();
1✔
354
        } else {
355
            pidString = EMPTY_PID;
1✔
356
        }
357

358
        xmlw.writeStartElement("docDscr");
1✔
359
        xmlw.writeStartElement("citation");
1✔
360
        xmlw.writeStartElement("titlStmt");
1✔
361
        XmlWriterUtil.writeFullElement(xmlw, "titl", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.title), datasetDto.getMetadataLanguage());
1✔
362
        xmlw.writeStartElement("IDNo");
1✔
363
        XmlWriterUtil.writeAttribute(xmlw, "agency", persistentAgency);
1✔
364
        xmlw.writeCharacters(pidString);
1✔
365
        xmlw.writeEndElement(); // IDNo
1✔
366
        xmlw.writeEndElement(); // titlStmt
1✔
367
        xmlw.writeStartElement("distStmt");
1✔
368
        //The doc is always published by the Dataverse Repository
369
        if (!StringUtils.isEmpty(datasetDto.getPublisher())) {
1✔
370
            xmlw.writeStartElement("distrbtr");
1✔
371
            xmlw.writeAttribute("source", "archive");
1✔
372
            xmlw.writeCharacters(datasetDto.getPublisher());
1✔
373
            xmlw.writeEndElement(); // distrbtr
1✔
374
        }
375
        XmlWriterUtil.writeFullElement(xmlw, "distDate", datasetDto.getPublicationDate());
1✔
376
        
377
        xmlw.writeEndElement(); // diststmt
1✔
378
        writeVersionStatement(xmlw, version);
1✔
379
        xmlw.writeStartElement("biblCit");
1✔
380
        xmlw.writeCharacters(version.getCitation());
1✔
381
        xmlw.writeEndElement(); // biblCit
1✔
382
        xmlw.writeEndElement(); // citation      
1✔
383
        xmlw.writeEndElement(); // docDscr
1✔
384
        
385
    }
1✔
386
    
387
    private static void writeVersionStatement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException{
388
        xmlw.writeStartElement("verStmt");
1✔
389
        xmlw.writeAttribute("source","archive");
1✔
390
        xmlw.writeStartElement("version");
1✔
391
        XmlWriterUtil.writeAttribute(xmlw,"date", datasetVersionDTO.getReleaseTime().substring(0, 10));
1✔
392
        XmlWriterUtil.writeAttribute(xmlw,"type", datasetVersionDTO.getVersionState().toString());
1✔
393
        xmlw.writeCharacters(datasetVersionDTO.getVersionNumber().toString());
1✔
394
        xmlw.writeEndElement(); // version
1✔
395
        xmlw.writeEndElement(); // verStmt
1✔
396
    }
1✔
397
    
398
    /* From the DDI 2.5 schema: 
399
            <xs:sequence>
400
               <xs:element ref="timePrd" minOccurs="0" maxOccurs="unbounded"/>
401
               <xs:element ref="collDate" minOccurs="0" maxOccurs="unbounded"/>
402
               <xs:element ref="nation" minOccurs="0" maxOccurs="unbounded"/>
403
               <xs:element ref="geogCover" minOccurs="0" maxOccurs="unbounded"/>
404
               <xs:element ref="geogUnit" minOccurs="0" maxOccurs="unbounded"/>
405
               <xs:element ref="geoBndBox" minOccurs="0"/>
406
               <xs:element ref="boundPoly" minOccurs="0" maxOccurs="unbounded"/>
407
               <xs:element ref="anlyUnit" minOccurs="0" maxOccurs="unbounded"/>
408
               <xs:element ref="universe" minOccurs="0" maxOccurs="unbounded"/>
409
               <xs:element ref="dataKind" minOccurs="0" maxOccurs="unbounded"/>
410
            </xs:sequence>
411
    */
412
    private static void writeSummaryDescriptionElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException {
413
        xmlw.writeStartElement("sumDscr");
1✔
414
        FieldDTO timePeriodCoveredDTO = null;
1✔
415
        FieldDTO dateOfCollectionDTO = null;
1✔
416
        FieldDTO geographicCoverageDTO = null;
1✔
417
        FieldDTO geographicBoundingBoxDTO = null;
1✔
418
        FieldDTO unitOfAnalysisDTO = null;
1✔
419
        FieldDTO universeDTO = null;
1✔
420
        FieldDTO kindOfDataDTO = null;
1✔
421

422
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
423
            String key = entry.getKey();
1✔
424
            MetadataBlockDTO value = entry.getValue();
1✔
425

426
            if ("citation".equals(key)) {
1✔
427
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
428
                    if (DatasetFieldConstant.timePeriodCovered.equals(fieldDTO.getTypeName())) {
1✔
429
                        timePeriodCoveredDTO = fieldDTO;
1✔
430
                    }
431

432
                    if (DatasetFieldConstant.dateOfCollection.equals(fieldDTO.getTypeName())) {
1✔
433
                        dateOfCollectionDTO = fieldDTO;
1✔
434
                    }
435

436
                    if (DatasetFieldConstant.kindOfData.equals(fieldDTO.getTypeName())) {
1✔
437
                        kindOfDataDTO = fieldDTO;
1✔
438
                    }
439
                }
1✔
440
            }
441

442
            if ("geospatial".equals(key)) {
1✔
443
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
444
                    if (DatasetFieldConstant.geographicCoverage.equals(fieldDTO.getTypeName())) {
1✔
445
                        geographicCoverageDTO = fieldDTO;
1✔
446
                    }
447
                    if (DatasetFieldConstant.geographicBoundingBox.equals(fieldDTO.getTypeName())) {
1✔
448

449
                        geographicBoundingBoxDTO = fieldDTO;
1✔
450

451
                    }
452
                }
1✔
453
            }
454

455
            if ("socialscience".equals(key)) {
1✔
456
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
457
                    if (DatasetFieldConstant.universe.equals(fieldDTO.getTypeName())) {
1✔
458
                        universeDTO = fieldDTO;
1✔
459
                    }
460
                    if (DatasetFieldConstant.unitOfAnalysis.equals(fieldDTO.getTypeName())) {
1✔
461
                        unitOfAnalysisDTO = fieldDTO;
1✔
462
                    }
463
                }
1✔
464
            }
465
        }
1✔
466
        /* Finally, we can write the fields we have collected, in the correct order: -L.A.*/
467

468
        if (timePeriodCoveredDTO != null) {
1✔
469
            String dateValStart = "";
1✔
470
            String dateValEnd = "";
1✔
471
            Integer per = 0;
1✔
472
            for (HashSet<FieldDTO> foo : timePeriodCoveredDTO.getMultipleCompound()) {
1✔
473
                per++;
1✔
474
                for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
475
                    FieldDTO next = iterator.next();
1✔
476
                    if (DatasetFieldConstant.timePeriodCoveredStart.equals(next.getTypeName())) {
1✔
477
                        dateValStart = next.getSinglePrimitive();
1✔
478
                    }
479
                    if (DatasetFieldConstant.timePeriodCoveredEnd.equals(next.getTypeName())) {
1✔
480
                        dateValEnd = next.getSinglePrimitive();
1✔
481
                    }
482
                }
1✔
483
                if (!dateValStart.isEmpty()) {
1✔
484
                    writeDateElement(xmlw, "timePrd", "P" + per.toString(), "start", dateValStart);
1✔
485
                }
486
                if (!dateValEnd.isEmpty()) {
1✔
487
                    writeDateElement(xmlw, "timePrd", "P" + per.toString(), "end", dateValEnd);
1✔
488
                }
489
            }
1✔
490
        }
491

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

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

519
            List<String> nationList = new ArrayList<>();
1✔
520
            List<String> geogCoverList = new ArrayList<>();
1✔
521

522
            for (HashSet<FieldDTO> foo : geographicCoverageDTO.getMultipleCompound()) {
1✔
523
                for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
524
                    FieldDTO next = iterator.next();
1✔
525
                    /* our "country" field maps 1:1 to the DDI "<nation>": */
526
                    if (DatasetFieldConstant.country.equals(next.getTypeName())) {
1✔
527
                        nationList.add(next.getSinglePrimitive());
1✔
528
                    }
529
                    /* city, state and otherGeographicCoverage all exported as "<geogCover>": */
530
                    if (DatasetFieldConstant.city.equals(next.getTypeName())
1✔
531
                            || DatasetFieldConstant.state.equals(next.getTypeName())
1✔
532
                            || DatasetFieldConstant.otherGeographicCoverage.equals(next.getTypeName())) {
1✔
533
                        geogCoverList.add(next.getSinglePrimitive());
1✔
534
                    }
535
                }
1✔
536
            }
1✔
537

538
            /**
539
             * And now we can write all the fields encountered, first the
540
             * "<nation>" entries, then all the "<geogCover>" ones:
541
             */
542
            for (String nationEntry : nationList) {
1✔
543
                XmlWriterUtil.writeFullElement(xmlw, "nation", nationEntry);
1✔
544
            }
1✔
545
            for (String geogCoverEntry : geogCoverList) {
1✔
546
                XmlWriterUtil.writeFullElement(xmlw, "geogCover", geogCoverEntry);
1✔
547
            }
1✔
548
        }
549

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

552
        /* Only 1 geoBndBox is allowed in the DDI.
553
           So, I'm just going to arbitrarily use the first one, and ignore the rest! -L.A. */
554
        if (geographicBoundingBoxDTO != null) {
1✔
555
            HashSet<FieldDTO> bndBoxSet = geographicBoundingBoxDTO.getMultipleCompound().get(0);
1✔
556
            xmlw.writeStartElement("geoBndBox");
1✔
557
            HashMap<String, String> geoBndBoxMap = new HashMap<>();
1✔
558
            for (FieldDTO next : bndBoxSet) {
1✔
559
                if (DatasetFieldConstant.westLongitude.equals(next.getTypeName())) {
1✔
560
                    geoBndBoxMap.put("westBL", next.getSinglePrimitive());
1✔
561
                }
562
                if (DatasetFieldConstant.eastLongitude.equals(next.getTypeName())) {
1✔
563
                    geoBndBoxMap.put("eastBL", next.getSinglePrimitive());
1✔
564
                }
565
                if (DatasetFieldConstant.northLatitude.equals(next.getTypeName())) {
1✔
566
                    geoBndBoxMap.put("northBL", next.getSinglePrimitive());
1✔
567
                }
568
                if (DatasetFieldConstant.southLatitude.equals(next.getTypeName())) {
1✔
569
                    geoBndBoxMap.put("southBL", next.getSinglePrimitive());
1✔
570
                }
571
            }
1✔
572

573
            /* Once again, order is important! */
574
 /*
575
                        <xs:sequence>
576
                            <xs:element ref="westBL"/>
577
                            <xs:element ref="eastBL"/>
578
                            <xs:element ref="southBL"/>
579
                            <xs:element ref="northBL"/>
580
                        </xs:sequence>
581
             */
582
            if (geoBndBoxMap.get("westBL") != null) {
1✔
583
                XmlWriterUtil.writeFullElement(xmlw, "westBL", geoBndBoxMap.get("westBL"));
1✔
584
            }
585
            if (geoBndBoxMap.get("eastBL") != null) {
1✔
586
                XmlWriterUtil.writeFullElement(xmlw, "eastBL", geoBndBoxMap.get("eastBL"));
1✔
587
            }
588
            if (geoBndBoxMap.get("southBL") != null) {
1✔
589
                XmlWriterUtil.writeFullElement(xmlw, "southBL", geoBndBoxMap.get("southBL"));
1✔
590
            }
591
            if (geoBndBoxMap.get("northBL") != null) {
1✔
592
                XmlWriterUtil.writeFullElement(xmlw, "northBL", geoBndBoxMap.get("northBL"));
1✔
593
            }
594

595
            xmlw.writeEndElement();
1✔
596
        }
597

598
        /* analyUnit: */
599
        if (unitOfAnalysisDTO != null) {
1✔
600
            XmlWriterUtil.writeI18NElementList(xmlw, "anlyUnit", unitOfAnalysisDTO.getMultipleVocab(), "unitOfAnalysis", unitOfAnalysisDTO.getTypeClass(), "socialscience", lang);
1✔
601

602
        }
603

604
        /* universe: */
605
        if (universeDTO != null) {
1✔
606
            writeMultipleElement(xmlw, "universe", universeDTO, lang);
1✔
607
        }
608

609
        /* finally, any "kind of data" entries: */
610
        if (kindOfDataDTO != null) {
1✔
611
            writeMultipleElement(xmlw, "dataKind", kindOfDataDTO, lang);
1✔
612
        }
613

614
        xmlw.writeEndElement(); //sumDscr     
1✔
615
    }
1✔
616
    
617
    private static void writeMultipleElement(XMLStreamWriter xmlw, String element, FieldDTO fieldDTO, String lang) throws XMLStreamException {
618
        for (String value : fieldDTO.getMultiplePrimitive()) {
1✔
619
            //Write multiple lang vals for controlled vocab, otherwise don't include any lang tag
620
            XmlWriterUtil.writeFullElement(xmlw, element, value, fieldDTO.isControlledVocabularyField() ? lang : null);
1✔
621
        }
1✔
622
    }
1✔
623
    
624
    private static void writeDateElement(XMLStreamWriter xmlw, String element, String cycle, String event, String dateIn) throws XMLStreamException {
625

626
        xmlw.writeStartElement(element);
1✔
627
        XmlWriterUtil.writeAttribute(xmlw, "cycle",  cycle);
1✔
628
        XmlWriterUtil.writeAttribute(xmlw, "event", event);
1✔
629
        XmlWriterUtil.writeAttribute(xmlw, "date", dateIn);
1✔
630
        xmlw.writeCharacters(dateIn);
1✔
631
        xmlw.writeEndElement(); 
1✔
632

633
    }
1✔
634
    
635
    /**
636
     * Again, <dataColl> is an xs:sequence - order is important and must follow
637
     * the schema. -L.A.
638
     * <xs:sequence>
639
     * <xs:element ref="timeMeth" minOccurs="0" maxOccurs="unbounded"/>
640
     * <xs:element ref="dataCollector" minOccurs="0" maxOccurs="unbounded"/>
641
     * <xs:element ref="collectorTraining" minOccurs="0" maxOccurs="unbounded"/>
642
     * <xs:element ref="frequenc" minOccurs="0" maxOccurs="unbounded"/>
643
     * <xs:element ref="sampProc" minOccurs="0" maxOccurs="unbounded"/>
644
     * <xs:element ref="sampleFrame" minOccurs="0" maxOccurs="unbounded"/>
645
     * <xs:element ref="targetSampleSize" minOccurs="0" maxOccurs="unbounded"/>
646
     * <xs:element ref="deviat" minOccurs="0" maxOccurs="unbounded"/>
647
     * <xs:element ref="collMode" minOccurs="0" maxOccurs="unbounded"/>
648
     * <xs:element ref="resInstru" minOccurs="0" maxOccurs="unbounded"/>
649
     * <xs:element ref="instrumentDevelopment" minOccurs="0" maxOccurs="unbounded"/>
650
     * <xs:element ref="sources" minOccurs="0"/>
651
     * <xs:element ref="collSitu" minOccurs="0" maxOccurs="unbounded"/>
652
     * <xs:element ref="actMin" minOccurs="0" maxOccurs="unbounded"/>
653
     * <xs:element ref="ConOps" minOccurs="0" maxOccurs="unbounded"/>
654
     * <xs:element ref="weight" minOccurs="0" maxOccurs="unbounded"/>
655
     * <xs:element ref="cleanOps" minOccurs="0" maxOccurs="unbounded"/>
656
     * </xs:sequence>
657
     */
658
    private static void writeMethodElement(XMLStreamWriter xmlw , DatasetVersionDTO version, String lang) throws XMLStreamException{
659
        xmlw.writeStartElement("method");
1✔
660
        xmlw.writeStartElement("dataColl");
1✔
661
        XmlWriterUtil.writeI18NElement(xmlw, "timeMeth", version, DatasetFieldConstant.timeMethod,lang);
1✔
662
        XmlWriterUtil.writeI18NElement(xmlw, "dataCollector", version, DatasetFieldConstant.dataCollector, lang);
1✔
663
        XmlWriterUtil.writeI18NElement(xmlw, "collectorTraining", version, DatasetFieldConstant.collectorTraining, lang);
1✔
664
        XmlWriterUtil.writeI18NElement(xmlw, "frequenc", version, DatasetFieldConstant.frequencyOfDataCollection, lang);
1✔
665
        XmlWriterUtil.writeI18NElement(xmlw, "sampProc", version, DatasetFieldConstant.samplingProcedure, lang);
1✔
666

667
        writeTargetSampleElement(xmlw, version);
1✔
668

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

671
        /* <collMode> comes before <sources>: */
672
        FieldDTO collModeFieldDTO = dto2FieldDTO(version, DatasetFieldConstant.collectionMode, "socialscience");
1✔
673
        if (collModeFieldDTO != null) {
1✔
674
            // This field was made multiple as of 5.10
675
            // Below is a backward compatibility check allowing export to work in 
676
            // an instance where the metadata block has not been updated yet.
677
            if (collModeFieldDTO.getMultiple()) {
1✔
678
                XmlWriterUtil.writeI18NElementList(xmlw, "collMode", collModeFieldDTO.getMultipleVocab(), DatasetFieldConstant.collectionMode, collModeFieldDTO.getTypeClass(), "socialscience", lang);
1✔
679
            } else {
680
                XmlWriterUtil.writeI18NElement(xmlw, "collMode", version, DatasetFieldConstant.collectionMode, lang);
×
681
            }
682
        }
683
        /* and so does <resInstru>: */
684
        XmlWriterUtil.writeI18NElement(xmlw, "resInstru", version, DatasetFieldConstant.researchInstrument, lang);
1✔
685
        xmlw.writeStartElement("sources");
1✔
686
        XmlWriterUtil.writeFullElementList(xmlw, "dataSrc", dto2PrimitiveList(version, DatasetFieldConstant.dataSources));
1✔
687
        XmlWriterUtil.writeI18NElement(xmlw, "srcOrig", version, DatasetFieldConstant.originOfSources, lang);
1✔
688
        XmlWriterUtil.writeI18NElement(xmlw, "srcChar", version, DatasetFieldConstant.characteristicOfSources, lang);
1✔
689
        XmlWriterUtil.writeI18NElement(xmlw, "srcDocu", version, DatasetFieldConstant.accessToSources, lang);
1✔
690
        xmlw.writeEndElement(); //sources
1✔
691

692
        
693
        XmlWriterUtil.writeI18NElement(xmlw, "collSitu", version, DatasetFieldConstant.dataCollectionSituation, lang);
1✔
694
        XmlWriterUtil.writeI18NElement(xmlw, "actMin", version, DatasetFieldConstant.actionsToMinimizeLoss, lang);
1✔
695
        /* "<ConOps>" has the uppercase C: */
696
        XmlWriterUtil.writeI18NElement(xmlw, "ConOps", version, DatasetFieldConstant.controlOperations, lang);
1✔
697
        XmlWriterUtil.writeI18NElement(xmlw, "weight", version, DatasetFieldConstant.weighting, lang);
1✔
698
        XmlWriterUtil.writeI18NElement(xmlw, "cleanOps", version, DatasetFieldConstant.cleaningOperations, lang);
1✔
699

700
        xmlw.writeEndElement(); //dataColl
1✔
701
        /* <notes> before <anlyInfo>: */
702
        writeNotesElement(xmlw, version);
1✔
703

704
        xmlw.writeStartElement("anlyInfo");
1✔
705
        //XmlWriterUtil.writeFullElement(xmlw, "anylInfo", dto2Primitive(version, DatasetFieldConstant.datasetLevelErrorNotes));
706
        XmlWriterUtil.writeI18NElement(xmlw, "respRate", version, DatasetFieldConstant.responseRate, lang);
1✔
707
        XmlWriterUtil.writeI18NElement(xmlw, "EstSmpErr", version, DatasetFieldConstant.samplingErrorEstimates, lang);
1✔
708
        XmlWriterUtil.writeI18NElement(xmlw, "dataAppr", version, DatasetFieldConstant.otherDataAppraisal, lang);
1✔
709
        xmlw.writeEndElement(); //anlyInfo
1✔
710
        
711
        xmlw.writeEndElement();//method
1✔
712
    }
1✔
713
    
714
    private static void writeSubjectElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException{ 
715
        
716
        //Key Words and Topic Classification
717
        Locale defaultLocale = Locale.getDefault();
1✔
718
        xmlw.writeStartElement("subject");
1✔
719
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
720
            String key = entry.getKey();
1✔
721
            MetadataBlockDTO value = entry.getValue();
1✔
722
            if (CITATION_BLOCK_NAME.equals(key)) {
1✔
723
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
724
                    if (DatasetFieldConstant.subject.equals(fieldDTO.getTypeName())) {
1✔
725
                        XmlWriterUtil.writeI18NElementList(xmlw, "keyword", fieldDTO.getMultipleVocab(), "subject",
1✔
726
                                fieldDTO.getTypeClass(), "citation", lang);
1✔
727
                    }
728

729
                    if (DatasetFieldConstant.keyword.equals(fieldDTO.getTypeName())) {
1✔
730
                        boolean isCVV = false;
1✔
731
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
732
                            String keywordValue = "";
1✔
733
                            String keywordVocab = "";
1✔
734
                            String keywordURI = "";
1✔
735
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
736
                                FieldDTO next = iterator.next();
1✔
737
                                if (DatasetFieldConstant.keywordValue.equals(next.getTypeName())) {
1✔
738
                                    if (next.isControlledVocabularyField()) {
1✔
739
                                        isCVV = true;
×
740
                                    }
741
                                    keywordValue = next.getSinglePrimitive();
1✔
742
                                }
743
                                if (DatasetFieldConstant.keywordVocab.equals(next.getTypeName())) {
1✔
744
                                    keywordVocab = next.getSinglePrimitive();
1✔
745
                                }
746
                                if (DatasetFieldConstant.keywordVocabURI.equals(next.getTypeName())) {
1✔
747
                                    keywordURI = next.getSinglePrimitive();
1✔
748
                                }
749
                            }
1✔
750
                            if (!keywordValue.isEmpty()) {
1✔
751
                                xmlw.writeStartElement("keyword");
1✔
752
                                XmlWriterUtil.writeAttribute(xmlw, "vocab", keywordVocab);
1✔
753
                                XmlWriterUtil.writeAttribute(xmlw, "vocabURI", keywordURI);
1✔
754
                                if (lang != null && isCVV) {
1✔
755
                                    XmlWriterUtil.writeAttribute(xmlw, "xml:lang", defaultLocale.getLanguage());
×
756
                                    xmlw.writeCharacters(ControlledVocabularyValue.getLocaleStrValue(keywordValue,
×
757
                                            DatasetFieldConstant.keywordValue, CITATION_BLOCK_NAME, defaultLocale,
758
                                            true));
759
                                } else {
760
                                    xmlw.writeCharacters(keywordValue);
1✔
761
                                }
762
                                xmlw.writeEndElement(); // Keyword
1✔
763
                                if (lang != null && isCVV && !defaultLocale.getLanguage().equals(lang)) {
1✔
764
                                    String translatedValue = ControlledVocabularyValue.getLocaleStrValue(keywordValue,
×
765
                                            DatasetFieldConstant.keywordValue, CITATION_BLOCK_NAME, new Locale(lang),
766
                                            false);
767
                                    if (translatedValue != null) {
×
768
                                        xmlw.writeStartElement("keyword");
×
769
                                        XmlWriterUtil.writeAttribute(xmlw, "vocab", keywordVocab);
×
770
                                        XmlWriterUtil.writeAttribute(xmlw, "vocabURI", keywordURI);
×
771
                                        XmlWriterUtil.writeAttribute(xmlw, "xml:lang", lang);
×
772
                                        xmlw.writeCharacters(translatedValue);
×
773
                                        xmlw.writeEndElement(); // Keyword
×
774
                                    }
775
                                }
776
                            }
777
                        }
1✔
778
                    }
779
                    if (DatasetFieldConstant.topicClassification.equals(fieldDTO.getTypeName())) {
1✔
780
                        boolean isCVV = false;
1✔
781
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
782
                            String topicClassificationValue = "";
1✔
783
                            String topicClassificationVocab = "";
1✔
784
                            String topicClassificationURI = "";
1✔
785
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
786
                                FieldDTO next = iterator.next();
1✔
787
                                if (DatasetFieldConstant.topicClassValue.equals(next.getTypeName())) {
1✔
788
                                    // Currently getSingleVocab() is the same as getSinglePrimitive() so this works
789
                                    // for either case
790
                                    topicClassificationValue = next.getSinglePrimitive();
1✔
791
                                    if (next.isControlledVocabularyField()) {
1✔
792
                                        isCVV = true;
×
793
                                    }
794
                                }
795
                                if (DatasetFieldConstant.topicClassVocab.equals(next.getTypeName())) {
1✔
796
                                    topicClassificationVocab = next.getSinglePrimitive();
1✔
797
                                }
798
                                if (DatasetFieldConstant.topicClassVocabURI.equals(next.getTypeName())) {
1✔
799
                                    topicClassificationURI = next.getSinglePrimitive();
1✔
800
                                }
801
                            }
1✔
802
                            if (!topicClassificationValue.isEmpty()) {
1✔
803
                                xmlw.writeStartElement("topcClas");
1✔
804
                                XmlWriterUtil.writeAttribute(xmlw, "vocab", topicClassificationVocab);
1✔
805
                                XmlWriterUtil.writeAttribute(xmlw, "vocabURI", topicClassificationURI);
1✔
806
                                if (lang != null && isCVV) {
1✔
807
                                    XmlWriterUtil.writeAttribute(xmlw, "xml:lang", defaultLocale.getLanguage());
×
808
                                    xmlw.writeCharacters(ControlledVocabularyValue.getLocaleStrValue(
×
809
                                            topicClassificationValue, DatasetFieldConstant.topicClassValue,
810
                                            CITATION_BLOCK_NAME, defaultLocale, true));
811
                                } else {
812
                                    xmlw.writeCharacters(topicClassificationValue);
1✔
813
                                }
814
                                xmlw.writeEndElement(); // topcClas
1✔
815
                                if (lang != null && isCVV && !defaultLocale.getLanguage().equals(lang)) {
1✔
816
                                    String translatedValue = ControlledVocabularyValue.getLocaleStrValue(
×
817
                                            topicClassificationValue, DatasetFieldConstant.topicClassValue,
818
                                            CITATION_BLOCK_NAME, new Locale(lang), false);
819
                                    if (translatedValue != null) {
×
820
                                        xmlw.writeStartElement("topcClas");
×
821
                                        XmlWriterUtil.writeAttribute(xmlw, "vocab", topicClassificationVocab);
×
822
                                        XmlWriterUtil.writeAttribute(xmlw, "vocabURI", topicClassificationURI);
×
823
                                        XmlWriterUtil.writeAttribute(xmlw, "xml:lang", lang);
×
824
                                        xmlw.writeCharacters(translatedValue);
×
825
                                        xmlw.writeEndElement(); // topcClas
×
826
                                    }
827
                                }
828
                            }
829
                        }
1✔
830
                    }
831
                }
1✔
832
            }
833
        }
1✔
834
        xmlw.writeEndElement(); // subject       
1✔
835
    }
1✔
836

837
    private static void writeAuthorsElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
838

839
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
840
            String key = entry.getKey();
1✔
841
            MetadataBlockDTO value = entry.getValue();
1✔
842
            if ("citation".equals(key)) {
1✔
843
                xmlw.writeStartElement("rspStmt");
1✔
844
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
845
                    if (DatasetFieldConstant.author.equals(fieldDTO.getTypeName())) {
1✔
846
                        String authorName = "";
1✔
847
                        String authorAffiliation = "";
1✔
848
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
849
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
850
                                FieldDTO next = iterator.next();
1✔
851
                                if (DatasetFieldConstant.authorName.equals(next.getTypeName())) {
1✔
852
                                    authorName =  next.getSinglePrimitive();
1✔
853
                                }
854
                                if (DatasetFieldConstant.authorAffiliation.equals(next.getTypeName())) {
1✔
855
                                    authorAffiliation =  next.getSinglePrimitive();
1✔
856
                                }
857
                            }
1✔
858
                            if (!authorName.isEmpty()){
1✔
859
                                xmlw.writeStartElement("AuthEnty"); 
1✔
860
                                XmlWriterUtil.writeAttribute(xmlw,"affiliation",authorAffiliation);
1✔
861
                                xmlw.writeCharacters(authorName);
1✔
862
                                xmlw.writeEndElement(); //AuthEnty
1✔
863
                            }
864
                        }
1✔
865

866
                    } else if (DatasetFieldConstant.contributor.equals(fieldDTO.getTypeName())) {
1✔
867
                        String contributorName = "";
1✔
868
                        String contributorType = "";
1✔
869
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
870
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
871
                                FieldDTO next = iterator.next();
1✔
872
                                if (DatasetFieldConstant.contributorName.equals(next.getTypeName())) {
1✔
873
                                    contributorName =  next.getSinglePrimitive();
1✔
874
                                }
875
                                if (DatasetFieldConstant.contributorType.equals(next.getTypeName())) {
1✔
876
                                    contributorType =  next.getSinglePrimitive();
1✔
877
                                }
878
                            }
1✔
879
                            if (!contributorName.isEmpty()){
1✔
880
                                xmlw.writeStartElement("othId");
1✔
881
                                XmlWriterUtil.writeAttribute(xmlw,"role", contributorType);
1✔
882
                                xmlw.writeCharacters(contributorName);
1✔
883
                                xmlw.writeEndElement(); //othId
1✔
884
                            }
885
                        }
1✔
886
                    }
887
                }
1✔
888
                xmlw.writeEndElement(); //rspStmt
1✔
889
            }
890

891
        }
1✔
892
    }
1✔
893
    
894
    private static void writeContactsElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
895

896
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
897
            String key = entry.getKey();
1✔
898
            MetadataBlockDTO value = entry.getValue();
1✔
899
            if ("citation".equals(key)) {
1✔
900
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
901
                    if (DatasetFieldConstant.datasetContact.equals(fieldDTO.getTypeName())) {
1✔
902
                        String datasetContactName = "";
1✔
903
                        String datasetContactAffiliation = "";
1✔
904
                        String datasetContactEmail = "";
1✔
905
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
906
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
907
                                FieldDTO next = iterator.next();
1✔
908
                                if (DatasetFieldConstant.datasetContactName.equals(next.getTypeName())) {
1✔
909
                                    datasetContactName =  next.getSinglePrimitive();
1✔
910
                                }
911
                                if (DatasetFieldConstant.datasetContactAffiliation.equals(next.getTypeName())) {
1✔
912
                                    datasetContactAffiliation =  next.getSinglePrimitive();
1✔
913
                                }
914
                                if (DatasetFieldConstant.datasetContactEmail.equals(next.getTypeName())) {
1✔
915
                                    datasetContactEmail = next.getSinglePrimitive();
1✔
916
                                }
917
                            }
1✔
918
                            // TODO: Since datasetContactEmail is a required field but datasetContactName is not consider not checking if datasetContactName is empty so we can write out datasetContactEmail.
919
                            if (!datasetContactName.isEmpty()){
1✔
920
                                xmlw.writeStartElement("contact"); 
1✔
921
                                XmlWriterUtil.writeAttribute(xmlw,"affiliation",datasetContactAffiliation);
1✔
922
                                XmlWriterUtil.writeAttribute(xmlw,"email",datasetContactEmail);
1✔
923
                                xmlw.writeCharacters(datasetContactName);
1✔
924
                                xmlw.writeEndElement(); //AuthEnty
1✔
925
                            }
926
                        }
1✔
927
                    }
928
                }
1✔
929
            }
930
        }
1✔
931
    }
1✔
932
    
933
    private static void writeProducersElement(XMLStreamWriter xmlw, DatasetVersionDTO version) throws XMLStreamException {
934
        xmlw.writeStartElement("prodStmt");
1✔
935
        for (Map.Entry<String, MetadataBlockDTO> entry : version.getMetadataBlocks().entrySet()) {
1✔
936
            String key = entry.getKey();
1✔
937
            MetadataBlockDTO value = entry.getValue();
1✔
938

939
            if ("citation".equals(key)) {
1✔
940
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
941
                    if (DatasetFieldConstant.producer.equals(fieldDTO.getTypeName())) {
1✔
942

943
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
944
                            String producerName = "";
1✔
945
                            String producerAffiliation = "";
1✔
946
                            String producerAbbreviation = "";
1✔
947
                            String producerLogo = "";
1✔
948
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
949
                                FieldDTO next = iterator.next();
1✔
950
                                if (DatasetFieldConstant.producerName.equals(next.getTypeName())) {
1✔
951
                                    producerName = next.getSinglePrimitive();
1✔
952
                                }
953
                                if (DatasetFieldConstant.producerAffiliation.equals(next.getTypeName())) {
1✔
954
                                    producerAffiliation = next.getSinglePrimitive();
1✔
955
                                }
956
                                if (DatasetFieldConstant.producerAbbreviation.equals(next.getTypeName())) {
1✔
957
                                    producerAbbreviation = next.getSinglePrimitive();
1✔
958
                                }
959
                                if (DatasetFieldConstant.producerLogo.equals(next.getTypeName())) {
1✔
960
                                    producerLogo = next.getSinglePrimitive();
1✔
961
                                }
962
                            }
1✔
963
                            if (!producerName.isEmpty()) {
1✔
964
                                xmlw.writeStartElement("producer");
1✔
965
                                XmlWriterUtil.writeAttribute(xmlw, "affiliation", producerAffiliation);
1✔
966
                                XmlWriterUtil.writeAttribute(xmlw, "abbr", producerAbbreviation);
1✔
967
                                //XmlWriterUtil.writeAttribute(xmlw, "role", producerLogo);
968
                                xmlw.writeCharacters(producerName);
1✔
969
                                xmlw.writeEndElement(); //AuthEnty
1✔
970
                            }
971
                        }
1✔
972
                        
973
                    }
974
                }
1✔
975
            }
976
        }
1✔
977
        XmlWriterUtil.writeFullElement(xmlw, "prodDate", XmlWriterUtil.dto2Primitive(version, DatasetFieldConstant.productionDate));
1✔
978
        // productionPlace was made multiple as of 5.14:
979
        // (a quick backward compatibility check was added to dto2PrimitiveList(),
980
        // see the method for details)
981

982
        FieldDTO  prodPlac = dto2FieldDTO( version, DatasetFieldConstant.productionPlace, "citation"  );
1✔
983
        if (prodPlac != null) {
1✔
984
            writeMultipleElement(xmlw, "prodPlac", prodPlac, null);
1✔
985
        }
986
        writeSoftwareElement(xmlw, version);
1✔
987
  
988
        writeGrantElement(xmlw, version);
1✔
989
        xmlw.writeEndElement(); //prodStmt
1✔
990
    }
1✔
991
    
992
    private static void writeDistributorsElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException {
993
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
994
            String key = entry.getKey();
1✔
995
            MetadataBlockDTO value = entry.getValue();
1✔
996
            if ("citation".equals(key)) {
1✔
997
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
998
                    if (DatasetFieldConstant.distributor.equals(fieldDTO.getTypeName())) {
1✔
999
                        //xmlw.writeStartElement("distrbtr");
1000
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1001
                            String distributorName = "";
1✔
1002
                            String distributorAffiliation = "";
1✔
1003
                            String distributorAbbreviation = "";
1✔
1004
                            String distributorURL = "";
1✔
1005
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1006
                                FieldDTO next = iterator.next();
1✔
1007
                                if (DatasetFieldConstant.distributorName.equals(next.getTypeName())) {
1✔
1008
                                    distributorName = next.getSinglePrimitive();
1✔
1009
                                }
1010
                                if (DatasetFieldConstant.distributorAffiliation.equals(next.getTypeName())) {
1✔
1011
                                    distributorAffiliation = next.getSinglePrimitive();
1✔
1012
                                }
1013
                                if (DatasetFieldConstant.distributorAbbreviation.equals(next.getTypeName())) {
1✔
1014
                                    distributorAbbreviation = next.getSinglePrimitive();
1✔
1015
                                }
1016
                                if (DatasetFieldConstant.distributorURL.equals(next.getTypeName())) {
1✔
1017
                                    distributorURL = next.getSinglePrimitive();
1✔
1018
                                }
1019
                            }
1✔
1020
                            if (!distributorName.isEmpty()) {
1✔
1021
                                xmlw.writeStartElement("distrbtr");
1✔
1022
                                if(DvObjectContainer.isMetadataLanguageSet(lang)) {
1✔
1023
                                    xmlw.writeAttribute("xml:lang", lang);
1✔
1024
                                }
1025
                                XmlWriterUtil.writeAttribute(xmlw, "affiliation", distributorAffiliation);
1✔
1026
                                XmlWriterUtil.writeAttribute(xmlw, "abbr", distributorAbbreviation);
1✔
1027
                                XmlWriterUtil.writeAttribute(xmlw, "URI", distributorURL);
1✔
1028
                                xmlw.writeCharacters(distributorName);
1✔
1029
                                xmlw.writeEndElement(); //AuthEnty
1✔
1030
                            }
1031
                        }
1✔
1032
                        //xmlw.writeEndElement(); //rspStmt
1033
                    }
1034

1035
                }
1✔
1036
            }
1037
        }
1✔
1038
    }
1✔
1039
    
1040
    private static void writeRelPublElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO) throws XMLStreamException {
1041
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1042
            String key = entry.getKey();
1✔
1043
            MetadataBlockDTO value = entry.getValue();
1✔
1044
            if ("citation".equals(key)) {
1✔
1045
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1046
                    if (DatasetFieldConstant.publication.equals(fieldDTO.getTypeName())) {
1✔
1047
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1048
                            String pubString = "";
1✔
1049
                            String citation = "";
1✔
1050
                            String IDType = "";
1✔
1051
                            String IDNo = "";
1✔
1052
                            String url = "";
1✔
1053
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1054
                                FieldDTO next = iterator.next();
1✔
1055
                                if (DatasetFieldConstant.publicationCitation.equals(next.getTypeName())) {
1✔
1056
                                    citation =  next.getSinglePrimitive();
1✔
1057
                                }
1058
                                if (DatasetFieldConstant.publicationIDType.equals(next.getTypeName())) {
1✔
1059
                                    IDType =  next.getSinglePrimitive();
1✔
1060
                                }
1061
                                if (DatasetFieldConstant.publicationIDNumber.equals(next.getTypeName())) {
1✔
1062
                                    IDNo =   next.getSinglePrimitive();
1✔
1063
                                }
1064
                                if (DatasetFieldConstant.publicationURL.equals(next.getTypeName())) {
1✔
1065
                                    url =  next.getSinglePrimitive();
1✔
1066
                                }
1067
                            }
1✔
1068
                            if (citation != null && !citation.trim().equals("")) {
1✔
1069
                                xmlw.writeStartElement("relPubl");
1✔
1070
                                xmlw.writeStartElement("citation");
1✔
1071
                                /* <xs:sequence>
1072
                                    <xs:element ref="titlStmt"/>
1073
                                    <xs:element ref="rspStmt" minOccurs="0"/>
1074
                                    <xs:element ref="prodStmt" minOccurs="0"/>
1075
                                    <xs:element ref="distStmt" minOccurs="0"/>
1076
                                    <xs:element ref="serStmt" minOccurs="0" maxOccurs="unbounded"/>
1077
                                    <xs:element ref="verStmt" minOccurs="0" maxOccurs="unbounded"/>
1078
                                    <xs:element ref="biblCit" minOccurs="0" maxOccurs="unbounded"/>
1079
                                    <xs:element ref="holdings" minOccurs="0" maxOccurs="unbounded"/>
1080
                                    <xs:element ref="notes" minOccurs="0" maxOccurs="unbounded"/>
1081
                                    <xs:group ref="dc:elementsAndRefinementsGroup"/>
1082
                                   </xs:sequence>
1083
                                 (In other words - titlStmt is mandatory! -L.A.)
1084
                                */
1085
                                xmlw.writeStartElement("titlStmt");
1✔
1086
                                XmlWriterUtil.writeFullElement(xmlw, "titl", citation);
1✔
1087
                                if (IDNo != null && !IDNo.trim().equals("")) {
1✔
1088

1089
                                    xmlw.writeStartElement("IDNo");
1✔
1090
                                    if (IDType != null && !IDType.trim().equals("")) {
1✔
1091
                                        xmlw.writeAttribute("agency", IDType);
1✔
1092
                                    }
1093
                                    xmlw.writeCharacters(IDNo);
1✔
1094
                                    xmlw.writeEndElement(); //IDNo
1✔
1095
                                }
1096
                                xmlw.writeEndElement(); // titlStmt
1✔
1097

1098

1099
                                XmlWriterUtil.writeFullElement(xmlw,"biblCit",citation);
1✔
1100
                                xmlw.writeEndElement(); //citation
1✔
1101
                                if (url != null && !url.trim().equals("") ) {
1✔
1102
                                    xmlw.writeStartElement("ExtLink");
1✔
1103
                                    xmlw.writeAttribute("URI", url);
1✔
1104
                                    xmlw.writeEndElement(); //ExtLink
1✔
1105
                                }
1106
                                xmlw.writeEndElement(); //relPubl
1✔
1107
                            }
1108
                        }
1✔
1109
                    }
1110
                }
1✔
1111
            }
1112
        }
1✔
1113
    }
1✔
1114
    
1115
    private static String appendCommaSeparatedValue(String inVal, String next) {
1116
        if (!next.isEmpty()) {
×
1117
            if (!inVal.isEmpty()) {
×
1118
                return inVal + ", " + next;
×
1119
            } else {
1120
                return next;
×
1121
            }
1122
        }
1123
        return inVal;
×
1124
    }
1125
    
1126
    private static void writeAbstractElement(XMLStreamWriter xmlw, DatasetVersionDTO datasetVersionDTO, String lang) throws XMLStreamException {
1127
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1128
            String key = entry.getKey();
1✔
1129
            MetadataBlockDTO value = entry.getValue();
1✔
1130
            if ("citation".equals(key)) {
1✔
1131
                for (FieldDTO fieldDTO : value.getFields()) {
1✔
1132
                    if (DatasetFieldConstant.description.equals(fieldDTO.getTypeName())) {
1✔
1133
                        String descriptionText = "";
1✔
1134
                        String descriptionDate = "";
1✔
1135
                        for (HashSet<FieldDTO> foo : fieldDTO.getMultipleCompound()) {
1✔
1136
                            for (Iterator<FieldDTO> iterator = foo.iterator(); iterator.hasNext();) {
1✔
1137
                                FieldDTO next = iterator.next();
1✔
1138
                                if (DatasetFieldConstant.descriptionText.equals(next.getTypeName())) {
1✔
1139
                                    descriptionText =  next.getSinglePrimitive();
1✔
1140
                                }
1141
                                if (DatasetFieldConstant.descriptionDate.equals(next.getTypeName())) {
1✔
1142
                                    descriptionDate =  next.getSinglePrimitive();
1✔
1143
                                }
1144
                            }
1✔
1145
                            if (!descriptionText.isEmpty()){
1✔
1146
                                xmlw.writeStartElement("abstract"); 
1✔
1147
                                XmlWriterUtil.writeAttribute(xmlw,"date",descriptionDate);
1✔
1148
                                if(DvObjectContainer.isMetadataLanguageSet(lang)) {
1✔
1149
                                    xmlw.writeAttribute("xml:lang", lang);
1✔
1150
                                }
1151
                                xmlw.writeCharacters(descriptionText);
1✔
1152
                                xmlw.writeEndElement(); //abstract
1✔
1153
                            }
1154
                        }
1✔
1155
                    }
1156
                }
1✔
1157
            }
1158
        }
1✔
1159
    }
1✔
1160

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

1439
                xmlw.writeAttribute("level", "datafile");
×
1440
                xmlw.writeStartElement("labl");
×
1441
                xmlw.writeCharacters(fileJson.getString("filename"));
×
1442
                xmlw.writeEndElement(); // labl
×
1443
                
1444
                if (fileJson.containsKey("description")) {
×
1445
                    xmlw.writeStartElement("txt");
×
1446
                    xmlw.writeCharacters(fileJson.getString("description"));
×
1447
                    xmlw.writeEndElement(); // txt
×
1448
                }
1449
                // there's no readily available field in the othermat section 
1450
                // for the content type (aka mime type); so we'll store it in this
1451
                // specially formatted notes section:
1452
                if (fileJson.containsKey("contentType")) {
×
1453
                    xmlw.writeStartElement("notes");
×
1454
                    xmlw.writeAttribute("level", LEVEL_FILE);
×
1455
                    xmlw.writeAttribute("type", NOTE_TYPE_CONTENTTYPE);
×
1456
                    xmlw.writeAttribute("subject", NOTE_SUBJECT_CONTENTTYPE);
×
1457
                    xmlw.writeCharacters(fileJson.getString("contentType"));
×
1458
                    xmlw.writeEndElement(); // notes
×
1459
                }
1460
                xmlw.writeEndElement(); // otherMat
×
1461
            }
1462
        }
1463
    }
1✔
1464
    
1465
    private static void writeFileDescription(XMLStreamWriter xmlw, FileDTO fileDTo) throws XMLStreamException {
1466
        xmlw.writeStartElement("txt");
1✔
1467
        String description = fileDTo.getDataFile().getDescription();
1✔
1468
        if (description != null) {
1✔
1469
            xmlw.writeCharacters(description);
1✔
1470
        }
1471
        xmlw.writeEndElement(); // txt
1✔
1472
    }
1✔
1473
    
1474

1475
    
1476
    private static List<String> dto2PrimitiveList(DatasetVersionDTO datasetVersionDTO, String datasetFieldTypeName) {
1477
        for (Map.Entry<String, MetadataBlockDTO> entry : datasetVersionDTO.getMetadataBlocks().entrySet()) {
1✔
1478
            MetadataBlockDTO value = entry.getValue();
1✔
1479
            for (FieldDTO fieldDTO : value.getFields()) {
1✔
1480
                if (datasetFieldTypeName.equals(fieldDTO.getTypeName())) {
1✔
1481
                    // This hack is here to make sure the export does not blow 
1482
                    // up on an instance that upgraded to a Dataverse version
1483
                    // where a certain primitive has been made multiple, but has
1484
                    // not yet update the block. 
1485
                    if (fieldDTO.getMultiple() != null && fieldDTO.getMultiple()) {
1✔
1486
                        return fieldDTO.getMultiplePrimitive();
1✔
1487
                    } else {
1488
                        return Arrays.asList(fieldDTO.getSinglePrimitive());
×
1489
                    }
1490
                }
1491
            }
1✔
1492
        }
1✔
1493
        return null;
1✔
1494
    }
1495
    
1496
    private static FieldDTO dto2FieldDTO(DatasetVersionDTO datasetVersionDTO, String datasetFieldTypeName, String metadataBlockName) {
1497
        MetadataBlockDTO block = datasetVersionDTO.getMetadataBlocks().get(metadataBlockName);
1✔
1498
        if (block != null) {
1✔
1499
            for (FieldDTO fieldDTO : block.getFields()) {
1✔
1500
                if (datasetFieldTypeName.equals(fieldDTO.getTypeName())) {
1✔
1501
                    return fieldDTO;
1✔
1502
                }
1503
            }
1✔
1504
        }
1505
        return null;
1✔
1506
    }
1507

1508

1509
    private static boolean StringUtilisEmpty(String str) {
1510
        if (str == null || str.trim().equals("")) {
1✔
1511
            return true;
×
1512
        }
1513
        return false;
1✔
1514
    }
1515

1516
    private static void saveJsonToDisk(String datasetVersionAsJson) throws IOException {
1517
        Files.write(Paths.get("/tmp/out.json"), datasetVersionAsJson.getBytes());
×
1518
    }
×
1519
    
1520
    
1521
    
1522
    
1523
    // Methods specific to the tabular data ("<dataDscr>") section. 
1524
    // Note that these do NOT operate on DTO objects, but instead directly 
1525
    // on Dataverse DataVariable, DataTable, etc. objects. 
1526
    // This is because for this release (4.5) we are recycling the already available 
1527
    // code, and this is what we got. (We already have DTO objects for DataTable, 
1528
    // and DataVariable, etc., but the current version JsonPrinter.jsonAsDatasetDto() 
1529
    // does not produce JSON for these objects - it stops at DataFile. Eventually 
1530
    // we want all of our objects to be exportable as JSON, and then all the exports
1531
    // can go through the same DTO state... But we don't have time for it now; 
1532
    // plus, the structure of file-level metadata is currently being re-designed, 
1533
    // so we probably should not invest any time into it right now). -- L.A. 4.5
1534
    
1535
    public static void createDataDscr(XMLStreamWriter xmlw, JsonArray fileDetails) throws XMLStreamException {
1536

1537
        if (fileDetails.isEmpty()) {
1✔
1538
            return;
1✔
1539
        }
1540

1541
        boolean tabularData = false;
×
1542

1543
        // we're not writing the opening <dataDscr> tag until we find an actual 
1544
        // tabular datafile.
1545
        for (int i=0;i<fileDetails.size();i++) {
×
1546
            JsonObject fileJson = fileDetails.getJsonObject(i);
×
1547

1548
            /**
1549
             * Previously (in Dataverse 5.3 and below) the dataDscr section was
1550
             * included for restricted files but that meant that summary
1551
             * statistics were exposed. (To get at these statistics, API users
1552
             * should instead use the "Data Variable Metadata Access" endpoint.)
1553
             * These days we skip restricted files to avoid this exposure.
1554
             */
1555
            if (fileJson.containsKey("restricted") && fileJson.getBoolean("restricted")) {
×
1556
                continue;
×
1557
            }
1558
            if(fileJson.containsKey("embargo")) {
×
1559
             String dateString = fileJson.getJsonObject("embargo").getString("dateAvailable");
×
1560
             LocalDate endDate = LocalDate.parse(dateString);
×
1561
             if (endDate != null && endDate.isAfter(LocalDate.now())) {
×
1562
                 //Embargo is active so skip
1563
                 continue;
×
1564
             }
1565
            }
1566
        
1567
            if (fileJson.containsKey("dataTables")) {
×
1568
                if (!tabularData) {
×
1569
                    xmlw.writeStartElement("dataDscr");
×
1570
                    tabularData = true;
×
1571
                }
1572
                if(fileJson.containsKey("varGroups")) {
×
1573
                    JsonArray varGroups = fileJson.getJsonArray("varGroups");
×
1574
                    for (int j=0;j<varGroups.size();j++){
×
1575
                        createVarGroupDDI(xmlw, varGroups.getJsonObject(j));
×
1576
                    }
1577
                }
1578
                JsonObject dataTable = fileJson.getJsonArray("dataTables").getJsonObject(0);
×
1579
                JsonArray vars = dataTable.getJsonArray("dataVariables");
×
1580
                if (vars != null) {
×
1581
                    for (int j = 0; j < vars.size(); j++) {
×
1582
                        createVarDDI(xmlw, vars.getJsonObject(j), fileJson.getJsonNumber("id").toString(),
×
1583
                                fileJson.getJsonNumber("fileMetadataId").toString());
×
1584
                    }
1585
                }
1586
            }
1587
        }
1588

1589
        if (tabularData) {
×
1590
            xmlw.writeEndElement(); // dataDscr
×
1591
        }
1592
    }
×
1593
    private static void createVarGroupDDI(XMLStreamWriter xmlw, JsonObject varGrp) throws XMLStreamException {
1594
        xmlw.writeStartElement("varGrp");
×
1595
        xmlw.writeAttribute("ID", "VG" + varGrp.getJsonNumber("id").toString());
×
1596
        String vars = "";
×
1597
        JsonArray varsInGroup = varGrp.getJsonArray("dataVariableIds");
×
1598
        for (int j=0;j<varsInGroup.size();j++){
×
1599
            vars = vars + " v" + varsInGroup.getString(j);
×
1600
        }
1601
        vars = vars.trim();
×
1602
        XmlWriterUtil.writeAttribute(xmlw, "var", vars );
×
1603

1604

1605
        if (varGrp.containsKey("label")) {
×
1606
            xmlw.writeStartElement("labl");
×
1607
            xmlw.writeCharacters(varGrp.getString("label"));
×
1608
            xmlw.writeEndElement(); // group label (labl)
×
1609
        }
1610

1611
        xmlw.writeEndElement(); //varGrp
×
1612
    }
×
1613
    
1614
    private static void createVarDDI(XMLStreamWriter xmlw, JsonObject dvar, String fileId, String fileMetadataId) throws XMLStreamException {
1615
        xmlw.writeStartElement("var");
×
1616
        xmlw.writeAttribute("ID", "v" + dvar.getJsonNumber("id").toString());
×
1617
        XmlWriterUtil.writeAttribute(xmlw, "name", dvar.getString("name"));
×
1618

1619
        JsonObject vm = null;
×
1620
        JsonArray vmArray = dvar.getJsonArray("variableMetadata"); 
×
1621
        for (int i=0;i< vmArray.size();i++) {
×
1622
            JsonObject curVm =vmArray.getJsonObject(i); 
×
1623
            if (curVm.containsKey("fileMetadataId") && curVm.getString("fileMetadataId").equals(fileMetadataId) ){
×
1624
                vm = curVm;
×
1625
                break;
×
1626
            }
1627
        }
1628

1629
        if (dvar.containsKey("numberOfDecimalPoints")) {
×
1630
            XmlWriterUtil.writeAttribute(xmlw, "dcml", dvar.getJsonNumber("numberOfDecimalPoints").toString());
×
1631
        }
1632

1633
        if (dvar.getBoolean("isOrderedCategorical")) {
×
1634
            xmlw.writeAttribute("nature", "ordinal");
×
1635
        }
1636

1637
        if (dvar.containsKey("variableIntervalType")) {
×
1638
            XmlWriterUtil.writeAttribute(xmlw, "intrvl", dvar.getString("variableIntervalType"));
×
1639
        }
1640

1641
        if (vm != null) {
×
1642
            if (vm.getBoolean("isWeightvar")) {
×
1643
                xmlw.writeAttribute("wgt", "wgt");
×
1644
            }
1645
            if (vm.containsKey("isWeighted") && vm.containsKey("weightVariableId")) {
×
1646
                xmlw.writeAttribute("wgt-var", "v"+vm.getString("weightVariableId"));
×
1647
            }
1648
        }
1649

1650
        // location
1651
        xmlw.writeEmptyElement("location");
×
1652
        if (dvar.containsKey("fileStartPosition")) {
×
1653
            XmlWriterUtil.writeAttribute(xmlw, "StartPos", dvar.getJsonNumber("fileStartPosition").toString());
×
1654
        }
1655
        if (dvar.containsKey("fileEndPosition")) {
×
1656
            XmlWriterUtil.writeAttribute(xmlw, "EndPos", dvar.getJsonNumber("fileEndPosition").toString());
×
1657
        }
1658
        if (dvar.containsKey("recordSegmentNumber")) {
×
1659
            XmlWriterUtil.writeAttribute(xmlw, "RecSegNo", dvar.getJsonNumber("recordSegmentNumber").toString());
×
1660
        }
1661

1662
        xmlw.writeAttribute("fileid", "f" + fileId);
×
1663

1664
        // labl
1665
        if ((vm == null || !vm.containsKey("label"))) {
×
1666
            if(dvar.containsKey("label")) {
×
1667
                xmlw.writeStartElement("labl");
×
1668
                xmlw.writeAttribute("level", "variable");
×
1669
                xmlw.writeCharacters(dvar.getString("label"));
×
1670
                xmlw.writeEndElement(); //labl
×
1671
            }
1672
        } else {
1673
            xmlw.writeStartElement("labl");
×
1674
            xmlw.writeAttribute("level", "variable");
×
1675
            xmlw.writeCharacters(vm.getString("label"));
×
1676
            xmlw.writeEndElement(); //labl
×
1677
        }
1678

1679
        if (vm != null) {
×
1680
            if (vm.containsKey("literalQuestion") || vm.containsKey("interviewInstruction") || vm.containsKey("postQuestion")) {
×
1681
                xmlw.writeStartElement("qstn");
×
1682
                if (vm.containsKey("literalQuestion")) {
×
1683
                    xmlw.writeStartElement("qstnLit");
×
1684
                    xmlw.writeCharacters(vm.getString("literalQuestion"));
×
1685
                    xmlw.writeEndElement(); // qstnLit
×
1686
                }
1687
                if (vm.containsKey("interviewInstruction")) {
×
1688
                    xmlw.writeStartElement("ivuInstr");
×
1689
                    xmlw.writeCharacters(vm.getString("interviewInstruction"));
×
1690
                    xmlw.writeEndElement(); //ivuInstr
×
1691
                }
1692
                if (vm.containsKey("postQuestion")) {
×
1693
                    xmlw.writeStartElement("postQTxt");
×
1694
                    xmlw.writeCharacters(vm.getString("postQuestion"));
×
1695
                    xmlw.writeEndElement(); //ivuInstr
×
1696
                }
1697
                xmlw.writeEndElement(); //qstn
×
1698
            }
1699
        }
1700

1701
        // invalrng
1702
        if (dvar.containsKey("invalidRanges")) {
×
1703
            boolean invalrngAdded = false;
×
1704
            JsonArray ranges = dvar.getJsonArray("invalidRanges");
×
1705
            for (int i = 0; i < ranges.size(); i++) {
×
1706
                JsonObject range = ranges.getJsonObject(0);
×
1707
                // if (range.getBeginValueType() != null &&
1708
                // range.getBeginValueType().getName().equals(DB_VAR_RANGE_TYPE_POINT)) {
1709
                if (range.getBoolean("hasBeginValueType") && range.getBoolean("isBeginValueTypePoint")) {
×
1710
                    if (range.containsKey("beginValue")) {
×
1711
                        invalrngAdded = XmlWriterUtil.writeOpenTagIfNeeded(xmlw, "invalrng", invalrngAdded);
×
1712
                        xmlw.writeEmptyElement("item");
×
1713
                        XmlWriterUtil.writeAttribute(xmlw, "VALUE", range.getString("beginValue"));
×
1714
                    }
1715
                } else {
1716
                    invalrngAdded = XmlWriterUtil.writeOpenTagIfNeeded(xmlw, "invalrng", invalrngAdded);
×
1717
                    xmlw.writeEmptyElement("range");
×
1718
                    if (range.getBoolean("hasBeginValueType") && range.containsKey("beginValue")) {
×
1719
                        if (range.getBoolean("isBeginValueTypeMin")) {
×
1720
                            XmlWriterUtil.writeAttribute(xmlw, "min", range.getString("beginValue"));
×
1721
                        } else if (range.getBoolean("isBeginValueTypeMinExcl")) {
×
1722
                            XmlWriterUtil.writeAttribute(xmlw, "minExclusive", range.getString("beginValue"));
×
1723
                        }
1724
                    }
1725
                    if (range.getBoolean("hasEndValueType") && range.containsKey("endValue")) {
×
1726
                        if (range.getBoolean("isEndValueTypeMax")) {
×
1727
                            XmlWriterUtil.writeAttribute(xmlw, "max", range.getString("endValue"));
×
1728
                        } else if (range.getBoolean("isEndValueTypeMaxExcl")) {
×
1729
                            XmlWriterUtil.writeAttribute(xmlw, "maxExclusive", range.getString("endValue"));
×
1730
                        }
1731
                    }
1732
                }
1733
            }
1734
            if (invalrngAdded) {
×
1735
                xmlw.writeEndElement(); // invalrng
×
1736
            }
1737
        }
1738

1739
        //universe
1740
        if (vm != null) {
×
1741
            if (vm.containsKey("universe")) {
×
1742
                xmlw.writeStartElement("universe");
×
1743
                xmlw.writeCharacters(vm.getString("universe"));
×
1744
                xmlw.writeEndElement(); //universe
×
1745
            }
1746
        }
1747

1748
        // sum stats
1749
        if (dvar.containsKey("summaryStatistics")) {
×
1750
            for (Entry<String, JsonValue> sumStat : dvar.getJsonObject("summaryStatistics").entrySet()) {
×
1751
                xmlw.writeStartElement("sumStat");
×
1752
                XmlWriterUtil.writeAttribute(xmlw, "type", sumStat.getKey());
×
1753
                xmlw.writeCharacters(((JsonString)sumStat.getValue()).getString());
×
1754
                xmlw.writeEndElement(); // sumStat
×
1755
            }
×
1756
        }
1757

1758
        // categories
1759
        if (dvar.containsKey("variableCategories")) {
×
1760
            JsonArray varCats = dvar.getJsonArray("variableCategories");
×
1761
            for (int i = 0; i < varCats.size(); i++) {
×
1762
                JsonObject varCat = varCats.getJsonObject(i);
×
1763
                xmlw.writeStartElement("catgry");
×
1764
                if (varCat.getBoolean("isMissing")) {
×
1765
                    xmlw.writeAttribute("missing", "Y");
×
1766
                }
1767

1768
                // catValu
1769
                xmlw.writeStartElement("catValu");
×
1770
                xmlw.writeCharacters(varCat.getString("value"));
×
1771
                xmlw.writeEndElement(); // catValu
×
1772

1773
                // label
1774
                if (varCat.containsKey("label")) {
×
1775
                    xmlw.writeStartElement("labl");
×
1776
                    xmlw.writeAttribute("level", "category");
×
1777
                    xmlw.writeCharacters(varCat.getString("label"));
×
1778
                    xmlw.writeEndElement(); // labl
×
1779
                }
1780

1781
                // catStat
1782
                if (varCat.containsKey("frequency")) {
×
1783
                    xmlw.writeStartElement("catStat");
×
1784
                    xmlw.writeAttribute("type", "freq");
×
1785
                    Double freq = varCat.getJsonNumber("frequency").doubleValue();
×
1786
                    // if frequency is actually a long value, we want to write "100" instead of
1787
                    // "100.0"
1788
                    if (Math.floor(freq) == freq) {
×
1789
                        xmlw.writeCharacters(Long.valueOf(freq.longValue()).toString());
×
1790
                    } else {
1791
                        xmlw.writeCharacters(freq.toString());
×
1792
                    }
1793
                    xmlw.writeEndElement(); // catStat
×
1794
                }
1795

1796
                // catStat weighted freq
1797
                if (vm != null && vm.getBoolean("isWeighted")) {
×
1798
                    JsonArray catMetas = vm.getJsonArray("categoryMetadatas");
×
1799
                    for (int j = 0; i < catMetas.size(); j++) {
×
1800
                        JsonObject cm = catMetas.getJsonObject(j);
×
1801
                        if (cm.getString("categoryValue").equals(varCat.getString("value"))) {
×
1802
                            xmlw.writeStartElement("catStat");
×
1803
                            xmlw.writeAttribute("wgtd", "wgtd");
×
1804
                            xmlw.writeAttribute("type", "freq");
×
1805
                            xmlw.writeCharacters(cm.getJsonNumber("wFreq").toString());
×
1806
                            xmlw.writeEndElement(); // catStat
×
1807
                            break;
×
1808
                        }
1809
                    }
1810
                }
1811

1812
                xmlw.writeEndElement(); // catgry
×
1813
            }
1814
        }
1815

1816

1817
        // varFormat
1818
        xmlw.writeEmptyElement("varFormat");
×
1819
        if(dvar.containsKey("variableFormatType")) {
×
1820
            XmlWriterUtil.writeAttribute(xmlw, "type", dvar.getString("variableFormatType").toLowerCase());
×
1821
        } else {
1822
            throw new XMLStreamException("Illegal Variable Format Type!");
×
1823
        }
1824
        if(dvar.containsKey("format")) {
×
1825
            XmlWriterUtil.writeAttribute(xmlw, "formatname", dvar.getString("format"));
×
1826
        }
1827
        //experiment writeAttribute(xmlw, "schema", dv.getFormatSchema());
1828
        if(dvar.containsKey("formatCategory")) {
×
1829
            XmlWriterUtil.writeAttribute(xmlw, "category", dvar.getString("formatCategory"));
×
1830
        }
1831

1832
        // notes
1833
        if (dvar.containsKey("UNF") && !dvar.getString("UNF").isBlank()) {
×
1834
            xmlw.writeStartElement("notes");
×
1835
            xmlw.writeAttribute("subject", "Universal Numeric Fingerprint");
×
1836
            xmlw.writeAttribute("level", "variable");
×
1837
            xmlw.writeAttribute("type", "Dataverse:UNF");
×
1838
            xmlw.writeCharacters(dvar.getString("UNF"));
×
1839
            xmlw.writeEndElement(); //notes
×
1840
        }
1841

1842
        if (vm != null) {
×
1843
            if (vm.containsKey("notes")) {
×
1844
                xmlw.writeStartElement("notes");
×
1845
                xmlw.writeCData(vm.getString("notes"));
×
1846
                xmlw.writeEndElement(); //notes CDATA
×
1847
            }
1848
        }
1849

1850

1851

1852
        xmlw.writeEndElement(); //var
×
1853

1854
    }
×
1855
    
1856
    private static void createFileDscr(XMLStreamWriter xmlw, JsonArray fileDetails) throws XMLStreamException {
1857
        String dataverseUrl = SystemConfig.getDataverseSiteUrlStatic();
1✔
1858
        for (int i =0;i<fileDetails.size();i++) {
1✔
1859
            JsonObject fileJson = fileDetails.getJsonObject(i);
×
1860
            //originalFileFormat is one of several keys that only exist for tabular data
1861
            if (fileJson.containsKey("originalFileFormat")) {
×
1862
                JsonObject dt = null;
×
1863
                if (fileJson.containsKey("dataTables")) {
×
1864
                    dt = fileJson.getJsonArray("dataTables").getJsonObject(0);
×
1865
                }
1866
                xmlw.writeStartElement("fileDscr");
×
1867
                String fileId = fileJson.getJsonNumber("id").toString();
×
1868
                xmlw.writeAttribute("ID", "f" + fileId);
×
1869
                xmlw.writeAttribute("URI", dataverseUrl + "/api/access/datafile/" + fileId);
×
1870

1871
                xmlw.writeStartElement("fileTxt");
×
1872
                xmlw.writeStartElement("fileName");
×
1873
                xmlw.writeCharacters(fileJson.getString("filename"));
×
1874
                xmlw.writeEndElement(); // fileName
×
1875

1876
                if (dt != null && (dt.containsKey("caseQuantity") || dt.containsKey("varQuantity")
×
1877
                        || dt.containsKey("recordsPerCase"))) {
×
1878
                    xmlw.writeStartElement("dimensns");
×
1879

1880
                    if (dt.containsKey("caseQuantity")) {
×
1881
                        xmlw.writeStartElement("caseQnty");
×
1882
                        xmlw.writeCharacters(dt.getJsonNumber("caseQuantity").toString());
×
1883
                        xmlw.writeEndElement(); // caseQnty
×
1884
                    }
1885

1886
                    if (dt.containsKey("varQuantity")) {
×
1887
                        xmlw.writeStartElement("varQnty");
×
1888
                        xmlw.writeCharacters(dt.getJsonNumber("varQuantity").toString());
×
1889
                        xmlw.writeEndElement(); // varQnty
×
1890
                    }
1891

1892
                    if (dt.containsKey("recordsPerCase")) {
×
1893
                        xmlw.writeStartElement("recPrCas");
×
1894
                        xmlw.writeCharacters(dt.getJsonNumber("recordsPerCase").toString());
×
1895
                        xmlw.writeEndElement(); // recPrCas
×
1896
                    }
1897

1898
                    xmlw.writeEndElement(); // dimensns
×
1899
                }
1900

1901
                xmlw.writeStartElement("fileType");
×
1902
                xmlw.writeCharacters(fileJson.getString("contentType"));
×
1903
                xmlw.writeEndElement(); // fileType
×
1904

1905
                xmlw.writeEndElement(); // fileTxt
×
1906

1907
                // various notes:
1908
                // this specially formatted note section is used to store the UNF
1909
                // (Universal Numeric Fingerprint) signature:
1910
                if ((dt!=null) && (dt.containsKey("UNF") && !dt.getString("UNF").isBlank())) {
×
1911
                    xmlw.writeStartElement("notes");
×
1912
                    xmlw.writeAttribute("level", LEVEL_FILE);
×
1913
                    xmlw.writeAttribute("type", NOTE_TYPE_UNF);
×
1914
                    xmlw.writeAttribute("subject", NOTE_SUBJECT_UNF);
×
1915
                    xmlw.writeCharacters(dt.getString("UNF"));
×
1916
                    xmlw.writeEndElement(); // notes
×
1917
                }
1918

1919
                if (fileJson.containsKey("tabularTags")) {
×
1920
                    JsonArray tags = fileJson.getJsonArray("tabularTags");
×
1921
                    for (int j = 0; j < tags.size(); j++) {
×
1922
                        xmlw.writeStartElement("notes");
×
1923
                        xmlw.writeAttribute("level", LEVEL_FILE);
×
1924
                        xmlw.writeAttribute("type", NOTE_TYPE_TAG);
×
1925
                        xmlw.writeAttribute("subject", NOTE_SUBJECT_TAG);
×
1926
                        xmlw.writeCharacters(tags.getString(j));
×
1927
                        xmlw.writeEndElement(); // notes
×
1928
                    }
1929
                }
1930

1931
                // TODO: add the remaining fileDscr elements!
1932
                xmlw.writeEndElement(); // fileDscr
×
1933
            }
1934
        }
1935
    }
1✔
1936
    
1937
    
1938

1939

1940

1941
    public static void datasetHtmlDDI(InputStream datafile, OutputStream outputStream) throws XMLStreamException {
1942
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1✔
1943

1944
        try {
1945
            Document document;
1946
            InputStream  styleSheetInput = DdiExportUtil.class.getClassLoader().getResourceAsStream("edu/harvard/iq/dataverse/codebook2-0.xsl");
1✔
1947

1948
            DocumentBuilder builder = factory.newDocumentBuilder();
1✔
1949
            document = builder.parse(datafile);
1✔
1950

1951
            // Use a Transformer for output
1952
            TransformerFactory tFactory = TransformerFactory.newInstance();
1✔
1953
            StreamSource stylesource = new StreamSource(styleSheetInput);
1✔
1954
            Transformer transformer = tFactory.newTransformer(stylesource);
1✔
1955

1956
            DOMSource source = new DOMSource(document);
1✔
1957
            StreamResult result = new StreamResult(outputStream);
1✔
1958
            transformer.transform(source, result);
1✔
1959
        } catch (TransformerConfigurationException tce) {
×
1960
            // Error generated by the parser
1961
            logger.severe("Transformer Factory error" + "   " + tce.getMessage());
×
1962
        } catch (TransformerException te) {
×
1963
            // Error generated by the parser
1964
            logger.severe("Transformation error" + "   " + te.getMessage());
×
1965

1966
        } catch (SAXException sxe) {
×
1967
            // Error generated by this application
1968
            // (or a parser-initialization error)
1969
            logger.severe("SAX error " + sxe.getMessage());
×
1970

1971
        } catch (ParserConfigurationException pce) {
×
1972
            // Parser with specified options can't be built
1973
            logger.severe("Parser configuration error " + pce.getMessage());
×
1974
        } catch (IOException ioe) {
×
1975
            // I/O error
1976
            logger.warning("I/O error " + ioe.getMessage());
×
1977
        }
1✔
1978

1979
    }
1✔
1980

1981
    public static void injectSettingsService(SettingsServiceBean settingsSvc) {
1982
        settingsService=settingsSvc;
1✔
1983
    }
1✔
1984

1985
}
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