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