001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.model.dataformat; 018 019import java.util.List; 020 021import javax.xml.bind.annotation.XmlAccessType; 022import javax.xml.bind.annotation.XmlAccessorType; 023import javax.xml.bind.annotation.XmlAttribute; 024import javax.xml.bind.annotation.XmlElement; 025import javax.xml.bind.annotation.XmlRootElement; 026 027import org.apache.camel.CamelContext; 028import org.apache.camel.model.DataFormatDefinition; 029import org.apache.camel.spi.DataFormat; 030import org.apache.camel.spi.Metadata; 031import org.apache.camel.util.CamelContextHelper; 032import org.apache.camel.util.ObjectHelper; 033 034/** 035 * The CSV data format is used for handling CSV payloads. 036 */ 037@Metadata(firstVersion = "1.3.0", label = "dataformat,transformation,csv", title = "CSV") 038@XmlRootElement(name = "csv") 039@XmlAccessorType(XmlAccessType.FIELD) 040public class CsvDataFormat extends DataFormatDefinition { 041 // Format options 042 @XmlAttribute @Metadata(label = "advanced") 043 private String formatRef; 044 @XmlAttribute @Metadata(enums = "DEFAULT,EXCEL,INFORMIX_UNLOAD,INFORMIX_UNLOAD_CSV,MYSQL,RFC4180") 045 private String formatName; 046 @XmlAttribute 047 private Boolean commentMarkerDisabled; 048 @XmlAttribute 049 private String commentMarker; 050 @XmlAttribute 051 private String delimiter; 052 @XmlAttribute 053 private Boolean escapeDisabled; 054 @XmlAttribute 055 private String escape; 056 @XmlAttribute 057 private Boolean headerDisabled; 058 @XmlElement 059 private List<String> header; 060 @XmlAttribute 061 private Boolean allowMissingColumnNames; 062 @XmlAttribute 063 private Boolean ignoreEmptyLines; 064 @XmlAttribute 065 private Boolean ignoreSurroundingSpaces; 066 @XmlAttribute 067 private Boolean nullStringDisabled; 068 @XmlAttribute 069 private String nullString; 070 @XmlAttribute 071 private Boolean quoteDisabled; 072 @XmlAttribute 073 private String quote; 074 @XmlAttribute 075 private String recordSeparatorDisabled; 076 @XmlAttribute 077 private String recordSeparator; 078 @XmlAttribute 079 private Boolean skipHeaderRecord; 080 @XmlAttribute 081 private String quoteMode; 082 @XmlAttribute 083 private Boolean ignoreHeaderCase; 084 @XmlAttribute 085 private Boolean trim; 086 @XmlAttribute 087 private Boolean trailingDelimiter; 088 089 // Unmarshall options 090 @XmlAttribute 091 private Boolean lazyLoad; 092 @XmlAttribute 093 private Boolean useMaps; 094 @XmlAttribute 095 private Boolean useOrderedMaps; 096 @XmlAttribute 097 private String recordConverterRef; 098 099 public CsvDataFormat() { 100 super("csv"); 101 } 102 103 public CsvDataFormat(String delimiter) { 104 this(); 105 setDelimiter(delimiter); 106 } 107 108 public CsvDataFormat(boolean lazyLoad) { 109 this(); 110 setLazyLoad(lazyLoad); 111 } 112 113 @Override 114 protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) { 115 // Format options 116 if (ObjectHelper.isNotEmpty(formatRef)) { 117 Object format = CamelContextHelper.mandatoryLookup(camelContext, formatRef); 118 setProperty(camelContext, dataFormat, "format", format); 119 } else if (ObjectHelper.isNotEmpty(formatName)) { 120 setProperty(camelContext, dataFormat, "formatName", formatName); 121 } 122 if (commentMarkerDisabled != null) { 123 setProperty(camelContext, dataFormat, "commentMarkerDisabled", commentMarkerDisabled); 124 } 125 if (commentMarker != null) { 126 setProperty(camelContext, dataFormat, "commentMarker", singleChar(commentMarker, "commentMarker")); 127 } 128 if (delimiter != null) { 129 setProperty(camelContext, dataFormat, "delimiter", singleChar(delimiter, "delimiter")); 130 } 131 if (escapeDisabled != null) { 132 setProperty(camelContext, dataFormat, "escapeDisabled", escapeDisabled); 133 } 134 if (escape != null) { 135 setProperty(camelContext, dataFormat, "escape", singleChar(escape, "escape")); 136 } 137 if (headerDisabled != null) { 138 setProperty(camelContext, dataFormat, "headerDisabled", headerDisabled); 139 } 140 if (header != null && !header.isEmpty()) { 141 setProperty(camelContext, dataFormat, "header", header.toArray(new String[header.size()])); 142 } 143 if (allowMissingColumnNames != null) { 144 setProperty(camelContext, dataFormat, "allowMissingColumnNames", allowMissingColumnNames); 145 } 146 if (ignoreEmptyLines != null) { 147 setProperty(camelContext, dataFormat, "ignoreEmptyLines", ignoreEmptyLines); 148 } 149 if (ignoreSurroundingSpaces != null) { 150 setProperty(camelContext, dataFormat, "ignoreSurroundingSpaces", ignoreSurroundingSpaces); 151 } 152 if (nullStringDisabled != null) { 153 setProperty(camelContext, dataFormat, "nullStringDisabled", nullStringDisabled); 154 } 155 if (nullString != null) { 156 setProperty(camelContext, dataFormat, "nullString", nullString); 157 } 158 if (quoteDisabled != null) { 159 setProperty(camelContext, dataFormat, "quoteDisabled", quoteDisabled); 160 } 161 if (quote != null) { 162 setProperty(camelContext, dataFormat, "quote", singleChar(quote, "quote")); 163 } 164 if (recordSeparatorDisabled != null) { 165 setProperty(camelContext, dataFormat, "recordSeparatorDisabled", recordSeparatorDisabled); 166 } 167 if (recordSeparator != null) { 168 setProperty(camelContext, dataFormat, "recordSeparator", recordSeparator); 169 } 170 if (skipHeaderRecord != null) { 171 setProperty(camelContext, dataFormat, "skipHeaderRecord", skipHeaderRecord); 172 } 173 if (quoteMode != null) { 174 setProperty(camelContext, dataFormat, "quoteMode", quoteMode); 175 } 176 if (trim != null) { 177 setProperty(camelContext, dataFormat, "trim", trim); 178 } 179 if (ignoreHeaderCase != null) { 180 setProperty(camelContext, dataFormat, "ignoreHeaderCase", ignoreHeaderCase); 181 } 182 if (trailingDelimiter != null) { 183 setProperty(camelContext, dataFormat, "trailingDelimiter", trailingDelimiter); 184 } 185 186 // Unmarshall options 187 if (lazyLoad != null) { 188 setProperty(camelContext, dataFormat, "lazyLoad", lazyLoad); 189 } 190 if (useMaps != null) { 191 setProperty(camelContext, dataFormat, "useMaps", useMaps); 192 } 193 if (useOrderedMaps != null) { 194 setProperty(camelContext, dataFormat, "useOrderedMaps", useOrderedMaps); 195 } 196 if (ObjectHelper.isNotEmpty(recordConverterRef)) { 197 Object recordConverter = CamelContextHelper.mandatoryLookup(camelContext, recordConverterRef); 198 setProperty(camelContext, dataFormat, "recordConverter", recordConverter); 199 } 200 } 201 202 private static Character singleChar(String value, String attributeName) { 203 if (value.length() != 1) { 204 throw new IllegalArgumentException(String.format("The '%s' attribute must be exactly one character long.", attributeName)); 205 } 206 return value.charAt(0); 207 } 208 209 public String getFormatRef() { 210 return formatRef; 211 } 212 213 /** 214 * The reference format to use, it will be updated with the other format options, the default value is CSVFormat.DEFAULT 215 */ 216 public void setFormatRef(String formatRef) { 217 this.formatRef = formatRef; 218 } 219 220 public String getFormatName() { 221 return formatName; 222 } 223 224 /** 225 * The name of the format to use, the default value is CSVFormat.DEFAULT 226 */ 227 public void setFormatName(String formatName) { 228 this.formatName = formatName; 229 } 230 231 public Boolean getCommentMarkerDisabled() { 232 return commentMarkerDisabled; 233 } 234 235 /** 236 * Disables the comment marker of the reference format. 237 */ 238 public void setCommentMarkerDisabled(Boolean commentMarkerDisabled) { 239 this.commentMarkerDisabled = commentMarkerDisabled; 240 } 241 242 public String getCommentMarker() { 243 return commentMarker; 244 } 245 246 /** 247 * Sets the comment marker of the reference format. 248 */ 249 public void setCommentMarker(String commentMarker) { 250 this.commentMarker = commentMarker; 251 } 252 253 public String getDelimiter() { 254 return delimiter; 255 } 256 257 /** 258 * Sets the delimiter to use. 259 * <p/> 260 * The default value is , (comma) 261 */ 262 public void setDelimiter(String delimiter) { 263 this.delimiter = delimiter; 264 } 265 266 public Boolean getEscapeDisabled() { 267 return escapeDisabled; 268 } 269 270 /** 271 * Use for disabling using escape character 272 */ 273 public void setEscapeDisabled(Boolean escapeDisabled) { 274 this.escapeDisabled = escapeDisabled; 275 } 276 277 public String getEscape() { 278 return escape; 279 } 280 281 /** 282 * Sets the escape character to use 283 */ 284 public void setEscape(String escape) { 285 this.escape = escape; 286 } 287 288 /** 289 * Use for disabling headers 290 */ 291 public Boolean getHeaderDisabled() { 292 return headerDisabled; 293 } 294 295 public void setHeaderDisabled(Boolean headerDisabled) { 296 this.headerDisabled = headerDisabled; 297 } 298 299 public List<String> getHeader() { 300 return header; 301 } 302 303 /** 304 * To configure the CSV headers 305 */ 306 public void setHeader(List<String> header) { 307 this.header = header; 308 } 309 310 public Boolean getAllowMissingColumnNames() { 311 return allowMissingColumnNames; 312 } 313 314 /** 315 * Whether to allow missing column names. 316 */ 317 public void setAllowMissingColumnNames(Boolean allowMissingColumnNames) { 318 this.allowMissingColumnNames = allowMissingColumnNames; 319 } 320 321 public Boolean getIgnoreEmptyLines() { 322 return ignoreEmptyLines; 323 } 324 325 /** 326 * Whether to ignore empty lines. 327 */ 328 public void setIgnoreEmptyLines(Boolean ignoreEmptyLines) { 329 this.ignoreEmptyLines = ignoreEmptyLines; 330 } 331 332 public Boolean getIgnoreSurroundingSpaces() { 333 return ignoreSurroundingSpaces; 334 } 335 336 /** 337 * Whether to ignore surrounding spaces 338 */ 339 public void setIgnoreSurroundingSpaces(Boolean ignoreSurroundingSpaces) { 340 this.ignoreSurroundingSpaces = ignoreSurroundingSpaces; 341 } 342 343 public Boolean getNullStringDisabled() { 344 return nullStringDisabled; 345 } 346 347 /** 348 * Used to disable null strings 349 */ 350 public void setNullStringDisabled(Boolean nullStringDisabled) { 351 this.nullStringDisabled = nullStringDisabled; 352 } 353 354 public String getNullString() { 355 return nullString; 356 } 357 358 /** 359 * Sets the null string 360 */ 361 public void setNullString(String nullString) { 362 this.nullString = nullString; 363 } 364 365 public Boolean getQuoteDisabled() { 366 return quoteDisabled; 367 } 368 369 /** 370 * Used to disable quotes 371 */ 372 public void setQuoteDisabled(Boolean quoteDisabled) { 373 this.quoteDisabled = quoteDisabled; 374 } 375 376 public String getQuote() { 377 return quote; 378 } 379 380 /** 381 * Sets the quote which by default is " 382 */ 383 public void setQuote(String quote) { 384 this.quote = quote; 385 } 386 387 public String getRecordSeparatorDisabled() { 388 return recordSeparatorDisabled; 389 } 390 391 /** 392 * Used for disabling record separator 393 */ 394 public void setRecordSeparatorDisabled(String recordSeparatorDisabled) { 395 this.recordSeparatorDisabled = recordSeparatorDisabled; 396 } 397 398 public String getRecordSeparator() { 399 return recordSeparator; 400 } 401 402 /** 403 * Sets the record separator (aka new line) which by default is new line characters (CRLF) 404 */ 405 public void setRecordSeparator(String recordSeparator) { 406 this.recordSeparator = recordSeparator; 407 } 408 409 public Boolean getSkipHeaderRecord() { 410 return skipHeaderRecord; 411 } 412 413 /** 414 * Whether to skip the header record in the output 415 */ 416 public void setSkipHeaderRecord(Boolean skipHeaderRecord) { 417 this.skipHeaderRecord = skipHeaderRecord; 418 } 419 420 public String getQuoteMode() { 421 return quoteMode; 422 } 423 424 /** 425 * Sets the quote mode 426 */ 427 public void setQuoteMode(String quoteMode) { 428 this.quoteMode = quoteMode; 429 } 430 431 public Boolean getLazyLoad() { 432 return lazyLoad; 433 } 434 435 /** 436 * Whether the unmarshalling should produce an iterator that reads the lines on the fly or if all the lines must be read at one. 437 */ 438 public void setLazyLoad(Boolean lazyLoad) { 439 this.lazyLoad = lazyLoad; 440 } 441 442 public Boolean getUseMaps() { 443 return useMaps; 444 } 445 446 /** 447 * Whether the unmarshalling should produce maps (HashMap)for the lines values instead of lists. It requires to have header (either defined or collected). 448 */ 449 public void setUseMaps(Boolean useMaps) { 450 this.useMaps = useMaps; 451 } 452 453 public Boolean getUseOrderedMaps() { 454 return useOrderedMaps; 455 } 456 457 /** 458 * Whether the unmarshalling should produce ordered maps (LinkedHashMap) for the lines values instead of lists. It requires to have header (either defined or collected). 459 */ 460 public void setUseOrderedMaps(Boolean useOrderedMaps) { 461 this.useOrderedMaps = useOrderedMaps; 462 } 463 464 public String getRecordConverterRef() { 465 return recordConverterRef; 466 } 467 468 /** 469 * Refers to a custom <tt>CsvRecordConverter</tt> to lookup from the registry to use. 470 */ 471 public void setRecordConverterRef(String recordConverterRef) { 472 this.recordConverterRef = recordConverterRef; 473 } 474 475 /** 476 * Sets whether or not to trim leading and trailing blanks. 477 */ 478 public void setTrim(Boolean trim) { 479 this.trim = trim; 480 } 481 482 public Boolean getTrim() { 483 return trim; 484 } 485 486 /** 487 * Sets whether or not to ignore case when accessing header names. 488 */ 489 public void setIgnoreHeaderCase(Boolean ignoreHeaderCase) { 490 this.ignoreHeaderCase = ignoreHeaderCase; 491 } 492 493 public Boolean getIgnoreHeaderCase() { 494 return ignoreHeaderCase; 495 } 496 497 /** 498 * Sets whether or not to add a trailing delimiter. 499 */ 500 public void setTrailingDelimiter(Boolean trailingDelimiter) { 501 this.trailingDelimiter = trailingDelimiter; 502 } 503 504 public Boolean getTrailingDelimiter() { 505 return trailingDelimiter; 506 } 507 508}