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