001/* 002 * Copyright 2018 Leibniz-Institut für Analytische Wissenschaften – ISAS – e.V.. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.isas.mztab2.io.serialization; 017 018import com.fasterxml.jackson.annotation.JsonProperty; 019import com.fasterxml.jackson.core.JsonGenerator; 020import com.fasterxml.jackson.databind.ObjectMapper; 021import com.fasterxml.jackson.databind.SerializerProvider; 022import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; 023import de.isas.mztab2.model.Assay; 024import de.isas.mztab2.model.IndexedElement; 025import de.isas.mztab2.model.OptColumnMapping; 026import de.isas.mztab2.model.Parameter; 027import de.isas.mztab2.model.StudyVariable; 028import de.isas.mztab2.model.Uri; 029import java.io.IOException; 030import java.util.Arrays; 031import java.util.Collections; 032import java.util.List; 033import java.util.Map; 034import java.util.Optional; 035import java.util.regex.Matcher; 036import java.util.regex.Pattern; 037import java.util.stream.Collectors; 038import java.util.stream.IntStream; 039import javax.validation.ValidationException; 040import lombok.extern.slf4j.Slf4j; 041import uk.ac.ebi.pride.jmztab2.model.IMZTabColumn; 042import uk.ac.ebi.pride.jmztab2.model.MZTabConstants; 043import static uk.ac.ebi.pride.jmztab2.model.MZTabConstants.NULL; 044import uk.ac.ebi.pride.jmztab2.model.MetadataElement; 045import uk.ac.ebi.pride.jmztab2.model.MetadataProperty; 046 047/** 048 * <p> 049 * Utility class providing helper methods for other serializers.</p> 050 * 051 * @author nilshoffmann 052 * @since 11/30/17 053 * 054 */ 055@Slf4j 056public class Serializers { 057 058 /** 059 * <p> 060 * getReference.</p> 061 * 062 * @param element a {@link java.lang.Object} object. 063 * @param idx a {@link java.lang.Integer} object. 064 * @return a {@link java.lang.String} object. 065 */ 066 public static String getReference(Object element, Integer idx) { 067 StringBuilder sb = new StringBuilder(); 068 sb.append(getElementName(element). 069 orElseThrow(() 070 -> { 071 return new IllegalArgumentException( 072 "No mzTab element name mapping available for " + element. 073 getClass(). 074 getName()); 075 })); 076 077 return sb.toString(); 078 } 079 080 /** 081 * <p> 082 * printAbundanceAssay.</p> 083 * 084 * @param a a {@link de.isas.mztab2.model.Assay} object. 085 * @return a {@link java.lang.String} object. 086 */ 087 public static String printAbundanceAssay(Assay a) { 088 StringBuilder sb = new StringBuilder(); 089 return sb.append("abundance_assay["). 090 append(a.getId()). 091 append("]"). 092 toString(); 093 } 094 095 /** 096 * <p> 097 * printAbundanceStudyVar.</p> 098 * 099 * @param sv a {@link de.isas.mztab2.model.StudyVariable} object. 100 * @return a {@link java.lang.String} object. 101 */ 102 public static String printAbundanceStudyVar(StudyVariable sv) { 103 StringBuilder sb = new StringBuilder(); 104 return sb.append("abundance_study_variable["). 105 append(sv.getId()). 106 append("]"). 107 toString(); 108 } 109 110 /** 111 * <p> 112 * printAbundanceCoeffVarStudyVar.</p> 113 * 114 * @param sv a {@link de.isas.mztab2.model.StudyVariable} object. 115 * @return a {@link java.lang.String} object. 116 */ 117 public static String printAbundanceCoeffVarStudyVar(StudyVariable sv) { 118 StringBuilder sb = new StringBuilder(); 119 return sb.append("abundance_coeffvar_study_variable["). 120 append(sv.getId()). 121 append("]"). 122 toString(); 123 } 124 125 /** 126 * <p> 127 * printOptColumnMapping.</p> 128 * 129 * @param ocm a {@link de.isas.mztab2.model.OptColumnMapping} object. 130 * @return a {@link java.lang.String} object. 131 */ 132 public static String printOptColumnMapping(OptColumnMapping ocm) { 133 StringBuilder sb = new StringBuilder(); 134 log.debug("Identifier={}; OptColumnMapping: {}", ocm.getIdentifier(), ocm); 135 if ("global".equals(ocm.getIdentifier())||ocm.getIdentifier().startsWith("global")) { 136 sb.append("opt_"); 137 sb.append(ocm.getIdentifier()); 138 if (ocm.getParam() != null) { 139 sb.append("_cv_"). 140 append(ocm.getParam(). 141 getCvAccession()). 142 append("_"). 143 append(ocm.getParam(). 144 getName(). 145 replaceAll(" ", "_")); 146 } 147 } else { 148 log.debug("OptColumnMapping: {}", ocm); 149 // object reference case, value is now the actual value 150 sb.append(ocm.getIdentifier()); 151 } 152 log.debug("asString: {}", sb.toString()); 153// //TODO: check for valid characters in definition 154// //valid characters: ‘A’-‘Z’, ‘a’-‘z’, ‘0’-‘9’, ‘’, ‘-’, ‘[’, ‘]’, and ‘:’. 155// //[A-Za-z0-9\[\]-:]+ 156 return sb.toString(); 157 } 158 159 /** 160 * <p> 161 * addIndexedLine for elements like assay[1] that have an id and one 162 * additional property element</p> 163 * 164 * @param <T> the type of {@link IndexedElement}. 165 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 166 * @param sp a {@link com.fasterxml.jackson.databind.SerializerProvider} 167 * object. 168 * @param prefix a {@link java.lang.String} object. 169 * @param element a {@link java.lang.Object} object. 170 * @param indexedElement a {@link de.isas.mztab2.model.Parameter} object. 171 */ 172 public static <T extends IndexedElement> void addIndexedLine( 173 JsonGenerator jg, SerializerProvider sp, String prefix, 174 Object element, T indexedElement) { 175 addIndexedLine(jg, sp, prefix, element, Arrays.asList(indexedElement)); 176 } 177 178 /** 179 * <p> 180 * addIndexedLine for elements like assay[1] that have an id and a list of 181 * additional property elements</p> 182 * 183 * @param <T> the type of {@link IndexedElement}. 184 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 185 * @param sp a {@link com.fasterxml.jackson.databind.SerializerProvider} 186 * object. 187 * @param prefix a {@link java.lang.String} object. 188 * @param element a {@link java.lang.Object} object. 189 * @param indexedElementList a {@link java.util.List} object. 190 */ 191 public static <T extends IndexedElement> void addIndexedLine( 192 JsonGenerator jg, SerializerProvider sp, String prefix, 193 Object element, 194 List<T> indexedElementList) { 195 Optional<List<T>> iel = Optional.ofNullable(indexedElementList); 196 if (!iel.isPresent() || indexedElementList.isEmpty()) { 197 198 log.debug( 199 "Skipping null or empty indexed element list values for {}", 200 getElementName( 201 element)); 202 return; 203 } 204 try { 205 jg.writeStartArray(); 206 //prefix 207 jg.writeString(prefix); 208 //key 209 jg.writeString(new StringBuilder().append(getElementName(element). 210 orElseThrow(() 211 -> { 212 return new ElementNameMappingException("unknown", element); 213 })). 214 toString()); 215 //value 216 jg.writeString(indexedElementList.stream(). 217 map((indexedElement) 218 -> { 219 if (indexedElement instanceof Parameter) { 220 return new ParameterConverter().convert( 221 (Parameter) indexedElement); 222 } else if (indexedElement instanceof Uri) { 223 return new UriConverter().convert((Uri) indexedElement); 224 } else { 225 throw new IllegalArgumentException( 226 "Serialization of type " + indexedElement.getClass() + " currently not supported!"); 227 } 228 }). 229 collect(Collectors.joining("|"))); 230 jg.writeEndArray(); 231 } catch (IOException ex) { 232 233 log.error("Caught IO Exception while trying to write indexed line:", 234 ex); 235 } 236 } 237 238 /** 239 * <p> 240 * addLineWithParameters.</p> 241 * 242 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 243 * @param prefix a {@link java.lang.String} object. 244 * @param element a {@link java.lang.Object} object. 245 * @param parameterList a {@link java.util.List} object. 246 */ 247 public static void addLineWithParameters(JsonGenerator jg, String prefix, 248 Object element, 249 List<Parameter> parameterList) { 250 if (parameterList == null || parameterList.isEmpty()) { 251 252 log.debug( 253 "Skipping null or empty parameter list values for " + getElementName( 254 element)); 255 return; 256 } 257 try { 258 jg.writeStartArray(); 259 //prefix 260 jg.writeString(prefix); 261 //key 262 jg.writeString(new StringBuilder().append(getElementName(element). 263 orElseThrow(() 264 -> { 265 return new ElementNameMappingException("unknown", element); 266 })). 267 toString()); 268 //value 269 jg.writeString(parameterList.stream(). 270 map((parameter) 271 -> { 272 return new ParameterConverter().convert(parameter); 273 }). 274 collect(Collectors.joining("|"))); 275 jg.writeEndArray(); 276 } catch (IOException ex) { 277 log.error( 278 "Caught IO Exception while trying to write line with parameters:", 279 ex); 280 } 281 } 282 283 /** 284 * <p> 285 * addLineWithPropertyParameters.</p> 286 * 287 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 288 * @param prefix a {@link java.lang.String} object. 289 * @param propertyName a {@link java.lang.String} object. 290 * @param element a {@link java.lang.Object} object. 291 * @param value a {@link java.util.List} object. 292 */ 293 public static void addLineWithPropertyParameters(JsonGenerator jg, 294 String prefix, 295 String propertyName, Object element, 296 List<Parameter> value) { 297 if (value == null || value.isEmpty()) { 298 299 log.debug("Skipping null or empty values for {}", 300 getElementName( 301 element)); 302 return; 303 } 304 addLineWithProperty(jg, prefix, propertyName, element, value.stream(). 305 map((parameter) 306 -> { 307 return new ParameterConverter().convert(parameter); 308 }). 309 collect(Collectors.joining("|"))); 310 } 311 312 /** 313 * <p> 314 * addLineWithMetadataProperty.</p> 315 * 316 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 317 * @param prefix a {@link java.lang.String} object. 318 * @param property a {@link uk.ac.ebi.pride.jmztab2.model.MetadataProperty} 319 * object. 320 * @param element a {@link java.lang.Object} object. 321 * @param value a {@link java.lang.Object} object. 322 */ 323 public static void addLineWithMetadataProperty(JsonGenerator jg, 324 String prefix, MetadataProperty property, Object element, 325 Object... value) { 326 addLineWithProperty(jg, prefix, property.getName(), element, value); 327 } 328 329 /** 330 * <p> 331 * addLineWithNullProperty.</p> 332 * 333 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 334 * @param prefix a {@link java.lang.String} object. 335 * @param propertyName a {@link java.lang.String} object. 336 * @param element a {@link java.lang.Object} object. 337 */ 338 public static void addLineWithNullProperty(JsonGenerator jg, String prefix, 339 String propertyName, Object element) { 340 try { 341 jg.writeStartArray(); 342 //prefix 343 jg.writeString(prefix); 344 //key 345 String key = getElementName(element). 346 orElseThrow(() 347 -> { 348 return new ElementNameMappingException(propertyName, element); 349 }); 350 if (propertyName == null) { 351 jg.writeString(key); 352 } else { 353 jg.writeString(key + "-" + propertyName); 354 } 355 //value 356 jg.writeString(NULL); 357 jg.writeEndArray(); 358 } catch (IOException ex) { 359 360 log.error( 361 "Caught exception while trying to write line with null property:", 362 ex); 363 } 364 } 365 366 /** 367 * <p> 368 * addLineWithProperty.</p> 369 * 370 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 371 * @param prefix a {@link java.lang.String} object. 372 * @param propertyName a {@link java.lang.String} object. 373 * @param element a {@link java.lang.Object} object. 374 * @param value a {@link java.lang.Object} object. 375 */ 376 public static void addLineWithProperty(JsonGenerator jg, String prefix, 377 String propertyName, Object element, 378 Object... value) { 379 if (value == null || value.length == 0) { 380 381 log.debug("Skipping null or empty values for {}", 382 getElementName( 383 element)); 384 return; 385 } 386 if (value.length == 1 && (value[0] == null)) { 387 388 log.debug("Skipping empty value for {}", getElementName( 389 element)); 390 return; 391 } 392 try { 393 jg.writeStartArray(); 394 //prefix 395 jg.writeString(prefix); 396 //key 397 String key = getElementName(element). 398 orElseThrow(() 399 -> { 400 return new ElementNameMappingException(propertyName, element); 401 }); 402 if (propertyName == null) { 403 jg.writeString(key); 404 } else { 405 jg.writeString(key + "-" + propertyName); 406 } 407 //value 408 for (Object o : value) { 409 jg.writeObject(o); 410 } 411 jg.writeEndArray(); 412 } catch (IOException ex) { 413 414 log.error( 415 "Caught IO exception while trying to write line with property:", 416 ex); 417 } 418 } 419 420 /** 421 * <p> 422 * addLine.</p> 423 * 424 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 425 * @param prefix a {@link java.lang.String} object. 426 * @param element a {@link java.lang.Object} object. 427 * @param value a {@link java.lang.Object} object. 428 */ 429 public static void addLine(JsonGenerator jg, String prefix, Object element, 430 Object... value) { 431 addLineWithProperty(jg, prefix, null, element, value); 432 } 433 434 /** 435 * <p> 436 * getElementName.</p> 437 * 438 * @param element a {@link java.lang.Object} object. 439 * @return a {@link java.util.Optional} object. 440 */ 441 public static Optional<String> getElementName(Object element) { 442 if (element instanceof String) { 443 return Optional.of((String) element); 444 } 445 if (element instanceof MetadataElement) { 446 return Optional.ofNullable(((MetadataElement) element).getName()); 447 } 448 JacksonXmlRootElement rootElement = element.getClass(). 449 getAnnotation(JacksonXmlRootElement.class); 450 if (rootElement != null) { 451 String underscoreName = camelCaseToUnderscoreLowerCase( 452 rootElement.localName()); 453 if (element instanceof IndexedElement) { 454 Integer id = Optional.ofNullable(((IndexedElement) element).getId()).orElseThrow(() -> 455 new NullPointerException( 456 "Field 'id' must not be null for element '" + underscoreName + "'!") 457 ); 458 return Optional.of( 459 underscoreName + "[" + id + "]"); 460 } 461 return Optional.ofNullable(underscoreName); 462 } 463 return Optional.empty(); 464 } 465 466 /** 467 * <p> 468 * getPropertyNames.</p> 469 * 470 * @param element a {@link java.lang.Object} object. 471 * @return a {@link java.util.List} object. 472 */ 473 public static List<String> getPropertyNames(Object element) { 474 return Arrays.asList(element.getClass(). 475 getAnnotationsByType(JsonProperty.class)). 476 stream(). 477 map((jsonProperty) 478 -> { 479 return jsonProperty.value(); 480 }). 481 collect(Collectors.toList()); 482 } 483 484 /** 485 * <p> 486 * asMap.</p> 487 * 488 * @param element a {@link java.lang.Object} object. 489 * @return a {@link java.util.Map} object. 490 */ 491 public static Map<String, Object> asMap(Object element) { 492 ObjectMapper objectMapper = new ObjectMapper(); 493 return objectMapper.convertValue(element, Map.class); 494 } 495 496 /** 497 * <p> 498 * camelCaseToUnderscoreLowerCase.</p> 499 * 500 * @param camelCase a {@link java.lang.String} object. 501 * @return a {@link java.lang.String} object. 502 */ 503 public static String camelCaseToUnderscoreLowerCase(String camelCase) { 504 Matcher m = Pattern.compile("(?<=[a-z])[A-Z]"). 505 matcher(camelCase); 506 507 StringBuffer sb = new StringBuffer(); 508 while (m.find()) { 509 m.appendReplacement(sb, "_" + m.group(). 510 toLowerCase()); 511 } 512 m.appendTail(sb); 513 return sb.toString(). 514 toLowerCase(); 515 } 516 517 /** 518 * <p> 519 * addSubElementStrings.</p> 520 * 521 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 522 * @param prefix a {@link java.lang.String} object. 523 * @param element a {@link java.lang.Object} object. 524 * @param subElementName a {@link java.lang.String} object. 525 * @param subElements a {@link java.util.List} object. 526 * @param oneLine a boolean. 527 */ 528 public static void addSubElementStrings(JsonGenerator jg, String prefix, 529 Object element, String subElementName, List<?> subElements, 530 boolean oneLine) { 531 if (checkForNull(element, subElements, subElementName)) { 532 return; 533 } 534 Serializers.getElementName(element). 535 ifPresent((elementName) 536 -> { 537 if (oneLine) { 538 addLine(jg, prefix, 539 elementName + "-" + subElementName, 540 subElements.stream(). 541 map((t) 542 -> { 543 return t.toString(); 544 }). 545 collect(Collectors.joining("" + MZTabConstants.BAR))); 546 } else { 547 IntStream.range(0, subElements. 548 size()). 549 forEachOrdered(i 550 -> { 551 addLine(jg, prefix, 552 elementName + "-" + subElementName + "[" + (i + 1) + "]", 553 subElements. 554 get(i)); 555 }); 556 } 557 }); 558 559 } 560 561 /** 562 * <p> 563 * addSubElementParameter.</p> 564 * 565 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 566 * @param prefix a {@link java.lang.String} object. 567 * @param element a {@link java.lang.Object} object. 568 * @param subElementName a {@link java.lang.String} object. 569 * @param subElement a {@link de.isas.mztab2.model.Parameter} object. 570 */ 571 public static void addSubElementParameter(JsonGenerator jg, String prefix, 572 Object element, String subElementName, Parameter subElement) { 573 if (subElement == null) { 574 String elementName = Serializers.getElementName(element). 575 orElse("undefined"); 576 577 log.debug("''{}-{}'' is null or empty!", new Object[]{ 578 elementName, 579 subElementName}); 580 return; 581 } 582 addSubElementStrings(jg, prefix, element, subElementName, Arrays.asList( 583 new ParameterConverter().convert(subElement)), true); 584 } 585 586 /** 587 * <p> 588 * addSubElementParameters.</p> 589 * 590 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 591 * @param prefix a {@link java.lang.String} object. 592 * @param element a {@link java.lang.Object} object. 593 * @param subElementName a {@link java.lang.String} object. 594 * @param subElements a {@link java.util.List} object. 595 * @param oneLine a boolean. 596 */ 597 public static void addSubElementParameters(JsonGenerator jg, String prefix, 598 Object element, String subElementName, List<Parameter> subElements, 599 boolean oneLine) { 600 if (checkForNull(element, subElements, subElementName)) { 601 return; 602 } 603 addSubElementStrings(jg, prefix, element, subElementName, 604 subElements.stream(). 605 map((parameter) 606 -> { 607 try { 608 return new ParameterConverter().convert(parameter); 609 } catch (IllegalArgumentException npe) { 610 611 log.debug("parameter is null for {}", 612 subElementName); 613 return "null"; 614 } 615 }). 616 collect(Collectors.toList()), oneLine); 617 } 618 619 /** 620 * <p> 621 * checkForNull.</p> 622 * 623 * @param element a {@link java.lang.Object} object. 624 * @param subElements a {@link java.util.List} object. 625 * @param subElementName a {@link java.lang.String} object. 626 * @return a boolean. 627 */ 628 public static boolean checkForNull(Object element, List<?> subElements, 629 String subElementName) { 630 String elementName = Serializers.getElementName(element). 631 orElse("undefined"); 632 if (subElements == null || subElements.isEmpty()) { 633 634 log.debug("''{}-{}'' is null or empty!", new Object[]{ 635 elementName, 636 subElementName}); 637 return true; 638 } 639 return false; 640 } 641 642 /** 643 * <p> 644 * writeString.</p> 645 * 646 * @param columnName a {@link java.lang.String} object. 647 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 648 * @param value a {@link java.lang.String} object. 649 * @throws java.io.IOException if an operation on the JsonGenerator object 650 * fails. 651 */ 652 public static void writeString(String columnName, JsonGenerator jg, 653 String value) throws IOException { 654 if (value == null) { 655 jg.writeNullField(columnName); 656 } else { 657 jg.writeStringField(columnName, value); 658 } 659 } 660 661 /** 662 * <p> 663 * writeString.</p> 664 * 665 * @param column a {@link uk.ac.ebi.pride.jmztab2.model.IMZTabColumn} 666 * object. 667 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 668 * @param value a {@link java.lang.String} object. 669 * @throws java.io.IOException if an operation on the JsonGenerator object 670 * fails. 671 */ 672 public static void writeString(IMZTabColumn column, JsonGenerator jg, 673 String value) throws IOException { 674 writeString(column.getHeader(), jg, value); 675 } 676 677 /** 678 * <p> 679 * writeObject.</p> 680 * 681 * @param columnName a {@link java.lang.String} object. 682 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 683 * @param sp a {@link com.fasterxml.jackson.databind.SerializerProvider} 684 * object. 685 * @param value a {@link java.lang.Object} object. 686 * @throws java.io.IOException if an operation on the JsonGenerator object 687 * fails. 688 */ 689 public static void writeObject(String columnName, JsonGenerator jg, 690 SerializerProvider sp, 691 Object value) throws IOException { 692 if (value == null) { 693 jg.writeNullField(columnName); 694 } else { 695 if (value instanceof Parameter) { 696 jg.writeStringField(columnName, new ParameterConverter(). 697 convert((Parameter) value)); 698 } else if (value instanceof String) { 699 jg.writeStringField(columnName, (String) value); 700 } else { 701 throw new IllegalArgumentException( 702 "Serialization of objects of type " + value.getClass() 703 + " currently not supported!"); 704 } 705 706 } 707 } 708 709 /** 710 * <p> 711 * writeObject.</p> 712 * 713 * @param column a {@link uk.ac.ebi.pride.jmztab2.model.IMZTabColumn} 714 * object. 715 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 716 * @param sp a {@link com.fasterxml.jackson.databind.SerializerProvider} 717 * object. 718 * @param value a {@link java.lang.Object} object. 719 * @throws java.io.IOException if an operation on the JsonGenerator object 720 * fails. 721 */ 722 public static void writeObject(IMZTabColumn column, JsonGenerator jg, 723 SerializerProvider sp, Object value) throws IOException { 724 writeObject(column.getHeader(), jg, sp, value); 725 } 726 727 /** 728 * <p> 729 * writeAsNumberArray.</p> 730 * 731 * @param column a {@link uk.ac.ebi.pride.jmztab2.model.IMZTabColumn} 732 * object. 733 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 734 * @param elements a {@link java.util.List} object. 735 */ 736 public static void writeAsNumberArray(IMZTabColumn column, JsonGenerator jg, 737 List<? extends Number> elements) { 738 writeAsNumberArray(column.getHeader(), jg, elements); 739 } 740 741 /** 742 * <p> 743 * writeAsNumberArray.</p> 744 * 745 * @param columnName a {@link java.lang.String} object. 746 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 747 * @param elements a {@link java.util.List} object. 748 */ 749 public static void writeAsNumberArray(String columnName, JsonGenerator jg, 750 List<? extends Number> elements) { 751 try { 752 if (elements == null) { 753 jg.writeNullField(columnName); 754 } else { 755 String arrayElements = elements.stream(). 756 map((number) 757 -> { 758 if (number == null) { 759 return MZTabConstants.NULL; 760 } else if (number instanceof Short) { 761 return "" + number.shortValue(); 762 } else if (number instanceof Integer) { 763 return "" + number.intValue(); 764 } else if (number instanceof Long) { 765 return "" + number.longValue(); 766 } else if (number instanceof Float) { 767 return "" + number.floatValue(); 768 } else { 769 return "" + number.doubleValue(); 770 } 771 }). 772 collect(Collectors.joining("" + MZTabConstants.BAR)); 773 if (arrayElements.isEmpty()) { 774 jg.writeNullField(columnName); 775 } else { 776 jg.writeStringField(columnName, arrayElements); 777 } 778 } 779 } catch (IOException ex) { 780 log.error( 781 "Caught IO exception while trying to write as number array: ", 782 ex); 783 } 784 } 785 786 /** 787 * <p> 788 * writeAsStringArray.</p> 789 * 790 * @param column a {@link uk.ac.ebi.pride.jmztab2.model.IMZTabColumn} 791 * object. 792 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 793 * @param elements a {@link java.util.List} object. 794 */ 795 public static void writeAsStringArray(IMZTabColumn column, JsonGenerator jg, 796 List<String> elements) { 797 writeAsStringArray(column.getHeader(), jg, elements); 798 } 799 800 /** 801 * <p> 802 * writeAsStringArray.</p> 803 * 804 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 805 * @param elements a {@link java.util.List} object. 806 */ 807 public static void writeAsStringArray(JsonGenerator jg, 808 List<String> elements) { 809 try { 810 if (elements == null) { 811 jg.writeNull(); 812 } else { 813 String arrayElements = elements.stream(). 814 map((t) 815 -> { 816 if (t == null) { 817 return MZTabConstants.NULL; 818 } 819 return t; 820 }). 821 collect(Collectors.joining("" + MZTabConstants.BAR)); 822 if (arrayElements.isEmpty()) { 823 jg.writeNull(); 824 } else { 825 jg.writeString(arrayElements); 826 } 827 } 828 } catch (IOException ex) { 829 log.error("Error while trying to write as string array:", ex); 830 } 831 } 832 833 /** 834 * <p> 835 * writeAsStringArray.</p> 836 * 837 * @param columnName a {@link java.lang.String} object. 838 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 839 * @param elements a {@link java.util.List} object. 840 */ 841 public static void writeAsStringArray(String columnName, JsonGenerator jg, 842 List<String> elements) { 843 try { 844 if (elements == null) { 845 jg.writeNullField(columnName); 846 } else { 847 String arrayElements = elements.stream(). 848 map((t) 849 -> { 850 if (t == null) { 851 return MZTabConstants.NULL; 852 } 853 return t; 854 }). 855 collect(Collectors.joining("" + MZTabConstants.BAR)); 856 if (arrayElements.isEmpty()) { 857 jg.writeNullField(columnName); 858 } else { 859 jg.writeStringField(columnName, arrayElements); 860 } 861 } 862 } catch (IOException ex) { 863 log.error("Error while trying to write as string array: ", ex); 864 } 865 } 866 867 /** 868 * <p> 869 * writeNumber.</p> 870 * 871 * @param columnName a {@link java.lang.String} object. 872 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 873 * @param value a {@link java.lang.Integer} object. 874 * @throws java.io.IOException if an operation on the JsonGenerator object 875 * fails. 876 */ 877 public static void writeNumber(String columnName, JsonGenerator jg, 878 Integer value) throws IOException { 879 if (value == null) { 880 jg.writeNullField(columnName); 881 } else { 882 jg.writeNumberField(columnName, value); 883 } 884 } 885 886 /** 887 * <p> 888 * writeNumber.</p> 889 * 890 * @param column a {@link uk.ac.ebi.pride.jmztab2.model.IMZTabColumn} 891 * object. 892 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 893 * @param value a {@link java.lang.Integer} object. 894 * @throws java.io.IOException if an operation on the JsonGenerator object 895 * fails. 896 */ 897 public static void writeNumber(IMZTabColumn column, JsonGenerator jg, 898 Integer value) throws IOException { 899 writeNumber(column.getHeader(), jg, value); 900 } 901 902 /** 903 * <p> 904 * writeNumber.</p> 905 * 906 * @param columnName a {@link java.lang.String} object. 907 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 908 * @param value a {@link java.lang.Double} object. 909 * @throws java.io.IOException if an operation on the JsonGenerator object 910 * fails. 911 */ 912 public static void writeNumber(String columnName, JsonGenerator jg, 913 Double value) throws IOException { 914 if (value == null) { 915 jg.writeNullField(columnName); 916 } else { 917 if (value.equals(Double.NaN)) { 918 jg.writeStringField(columnName, MZTabConstants.CALCULATE_ERROR); 919 } else if (value.equals(Double.POSITIVE_INFINITY)) { 920 jg.writeStringField(columnName, MZTabConstants.INFINITY); 921 } else { 922 jg.writeNumberField(columnName, value); 923 } 924 } 925 } 926 927 /** 928 * <p> 929 * writeNumber.</p> 930 * 931 * @param column a {@link uk.ac.ebi.pride.jmztab2.model.IMZTabColumn} 932 * object. 933 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 934 * @param value a {@link java.lang.Double} object. 935 * @throws java.io.IOException if an operation on the JsonGenerator object 936 * fails. 937 */ 938 public static void writeNumber(IMZTabColumn column, JsonGenerator jg, 939 Double value) throws IOException { 940 writeNumber(column.getHeader(), jg, value); 941 } 942 943 /** 944 * <p> 945 * writeNumber.</p> 946 * 947 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 948 * @param value a {@link java.lang.Integer} object. 949 * @throws java.io.IOException if an operation on the JsonGenerator object 950 * fails. 951 */ 952 public static void writeNumber(JsonGenerator jg, Integer value) throws IOException { 953 if (value == null) { 954 jg.writeNull(); 955 } else { 956 jg.writeNumber(value); 957 } 958 } 959 960 /** 961 * <p> 962 * writeNumber.</p> 963 * 964 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 965 * @param value a {@link java.lang.Double} object. 966 * @throws java.io.IOException if an operation on the JsonGenerator object 967 * fails. 968 */ 969 public static void writeNumber(JsonGenerator jg, Double value) throws IOException { 970 if (value == null) { 971 jg.writeNull(); 972 } else { 973 jg.writeNumber(value); 974 } 975 } 976 977 /** 978 * <p> 979 * writeOptColumnMappings.</p> 980 * 981 * @param optColumnMappings a {@link java.util.List} object. 982 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 983 * @param sp the serialization provider. 984 * @throws java.io.IOException if an operation on the JsonGenerator object 985 * fails. 986 */ 987 public static void writeOptColumnMappings( 988 List<OptColumnMapping> optColumnMappings, 989 JsonGenerator jg, SerializerProvider sp) throws IOException { 990 for (OptColumnMapping ocm : Optional.ofNullable( 991 optColumnMappings). 992 orElse(Collections.emptyList())) { 993 // write global or indexed element param objects 994 if (ocm.getParam() != null) { 995 writeObject(Serializers.printOptColumnMapping(ocm), jg, sp, ocm. 996 getValue() == null ? 997 (ocm.getParam().getValue() == null || ocm.getParam().getValue().isEmpty() ? 998 NULL : ocm.getParam().getValue()) : ocm.getValue()); 999 } else { // write global opt column objects with the value 1000 writeObject(Serializers.printOptColumnMapping(ocm), jg, sp, ocm. 1001 getValue() == null ? NULL : ocm.getValue()); 1002 } 1003 } 1004 } 1005 1006 /** 1007 * <p> 1008 * writeIndexedValues.</p> 1009 * 1010 * @param prefix a {@link java.lang.String} object. 1011 * @param jg a {@link com.fasterxml.jackson.core.JsonGenerator} object. 1012 * @param values a {@link java.util.List} object. 1013 */ 1014 public static void writeIndexedDoubles(String prefix, 1015 JsonGenerator jg, List<Double> values) { 1016 IntStream.range(0, values. 1017 size()). 1018 forEachOrdered(i 1019 -> { 1020 try { 1021 Serializers.writeNumber( 1022 prefix + "[" + (i + 1) + "]", 1023 jg, 1024 values. 1025 get(i)); 1026 } catch (IOException ex) { 1027 log.error( 1028 "Caught IO exception while trying to write indexed doubles:", 1029 ex); 1030 } 1031 }); 1032 } 1033 1034 public static void checkIndexedElement(IndexedElement element) { 1035 Integer id = Optional.ofNullable(element.getId()).orElseThrow(() -> 1036 new ValidationException( 1037 "'id' field of " + element.toString() + " must not be null!")); 1038 if (id < 1) { 1039 throw new ValidationException( 1040 "'id' field of " + element.toString() + " must have a value greater to equal to 1!"); 1041 } 1042 } 1043 1044}