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.ArrayList; 020import java.util.List; 021import javax.xml.bind.annotation.XmlAccessType; 022import javax.xml.bind.annotation.XmlAccessorType; 023import javax.xml.bind.annotation.XmlAttribute; 024import javax.xml.bind.annotation.XmlElementRef; 025 026import org.apache.camel.CamelContext; 027import org.apache.camel.model.DataFormatDefinition; 028import org.apache.camel.spi.DataFormat; 029import org.apache.camel.spi.Metadata; 030 031/** 032 * Represents the common parts of all uniVocity {@link org.apache.camel.spi.DataFormat} parsers. 033 */ 034@Metadata(label = "dataformat,transformation,csv", title = "uniVocity") 035@XmlAccessorType(XmlAccessType.FIELD) 036public abstract class UniVocityAbstractDataFormat extends DataFormatDefinition { 037 038 @XmlAttribute 039 protected String nullValue; 040 @XmlAttribute @Metadata(defaultValue = "true") 041 protected Boolean skipEmptyLines; 042 @XmlAttribute @Metadata(defaultValue = "true") 043 protected Boolean ignoreTrailingWhitespaces; 044 @XmlAttribute @Metadata(defaultValue = "true") 045 protected Boolean ignoreLeadingWhitespaces; 046 @XmlAttribute 047 protected Boolean headersDisabled; 048 @XmlElementRef 049 protected List<UniVocityHeader> headers; 050 @XmlAttribute 051 protected Boolean headerExtractionEnabled; 052 @XmlAttribute 053 protected Integer numberOfRecordsToRead; 054 @XmlAttribute 055 protected String emptyValue; 056 @XmlAttribute 057 protected String lineSeparator; 058 @XmlAttribute @Metadata(defaultValue = "\\n") 059 protected String normalizedLineSeparator; 060 @XmlAttribute @Metadata(defaultValue = "#") 061 protected String comment; 062 @XmlAttribute 063 protected Boolean lazyLoad; 064 @XmlAttribute 065 protected Boolean asMap; 066 067 protected UniVocityAbstractDataFormat() { 068 // This constructor is needed by jaxb for schema generation 069 } 070 071 protected UniVocityAbstractDataFormat(String dataFormatName) { 072 super(dataFormatName); 073 } 074 075 public String getNullValue() { 076 return nullValue; 077 } 078 079 /** 080 * The string representation of a null value. 081 * <p/> 082 * The default value is null 083 */ 084 public void setNullValue(String nullValue) { 085 this.nullValue = nullValue; 086 } 087 088 public Boolean getSkipEmptyLines() { 089 return skipEmptyLines; 090 } 091 092 /** 093 * Whether or not the empty lines must be ignored. 094 * <p/> 095 * The default value is true 096 */ 097 public void setSkipEmptyLines(Boolean skipEmptyLines) { 098 this.skipEmptyLines = skipEmptyLines; 099 } 100 101 public Boolean getIgnoreTrailingWhitespaces() { 102 return ignoreTrailingWhitespaces; 103 } 104 105 /** 106 * Whether or not the trailing white spaces must ignored. 107 * <p/> 108 * The default value is true 109 */ 110 public void setIgnoreTrailingWhitespaces(Boolean ignoreTrailingWhitespaces) { 111 this.ignoreTrailingWhitespaces = ignoreTrailingWhitespaces; 112 } 113 114 public Boolean getIgnoreLeadingWhitespaces() { 115 return ignoreLeadingWhitespaces; 116 } 117 118 /** 119 * Whether or not the leading white spaces must be ignored. 120 * <p/> 121 * The default value is true 122 */ 123 public void setIgnoreLeadingWhitespaces(Boolean ignoreLeadingWhitespaces) { 124 this.ignoreLeadingWhitespaces = ignoreLeadingWhitespaces; 125 } 126 127 public Boolean getHeadersDisabled() { 128 return headersDisabled; 129 } 130 131 /** 132 * Whether or not the headers are disabled. When defined, this option explicitly sets the headers as null which indicates that there is no header. 133 * <p/> 134 * The default value is false 135 */ 136 public void setHeadersDisabled(Boolean headersDisabled) { 137 this.headersDisabled = headersDisabled; 138 } 139 140 public List<UniVocityHeader> getHeaders() { 141 return headers; 142 } 143 144 /** 145 * The headers to use. 146 */ 147 public void setHeaders(List<UniVocityHeader> headers) { 148 this.headers = headers; 149 } 150 151 public Boolean getHeaderExtractionEnabled() { 152 return headerExtractionEnabled; 153 } 154 155 /** 156 * Whether or not the header must be read in the first line of the test document 157 * <p/> 158 * The default value is false 159 */ 160 public void setHeaderExtractionEnabled(Boolean headerExtractionEnabled) { 161 this.headerExtractionEnabled = headerExtractionEnabled; 162 } 163 164 public Integer getNumberOfRecordsToRead() { 165 return numberOfRecordsToRead; 166 } 167 168 /** 169 * The maximum number of record to read. 170 */ 171 public void setNumberOfRecordsToRead(Integer numberOfRecordsToRead) { 172 this.numberOfRecordsToRead = numberOfRecordsToRead; 173 } 174 175 public String getEmptyValue() { 176 return emptyValue; 177 } 178 179 /** 180 * The String representation of an empty value 181 */ 182 public void setEmptyValue(String emptyValue) { 183 this.emptyValue = emptyValue; 184 } 185 186 public String getLineSeparator() { 187 return lineSeparator; 188 } 189 190 /** 191 * The line separator of the files 192 * <p/> 193 * The default value is to use the JVM platform line separator 194 */ 195 public void setLineSeparator(String lineSeparator) { 196 this.lineSeparator = lineSeparator; 197 } 198 199 public String getNormalizedLineSeparator() { 200 return normalizedLineSeparator; 201 } 202 203 /** 204 * The normalized line separator of the files 205 * <p/> 206 * The default value is a new line character. 207 */ 208 public void setNormalizedLineSeparator(String normalizedLineSeparator) { 209 this.normalizedLineSeparator = normalizedLineSeparator; 210 } 211 212 public String getComment() { 213 return comment; 214 } 215 216 /** 217 * The comment symbol. 218 * <p/> 219 * The default value is # 220 */ 221 public void setComment(String comment) { 222 this.comment = comment; 223 } 224 225 public Boolean getLazyLoad() { 226 return lazyLoad; 227 } 228 229 /** 230 * Whether the unmarshalling should produce an iterator that reads the lines on the fly or if all the lines must be read at one. 231 * <p/> 232 * The default value is false 233 */ 234 public void setLazyLoad(Boolean lazyLoad) { 235 this.lazyLoad = lazyLoad; 236 } 237 238 public Boolean getAsMap() { 239 return asMap; 240 } 241 242 /** 243 * Whether the unmarshalling should produce maps for the lines values instead of lists. 244 * It requires to have header (either defined or collected). 245 * <p/> 246 * The default value is false 247 */ 248 public void setAsMap(Boolean asMap) { 249 this.asMap = asMap; 250 } 251 252 @Override 253 protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) { 254 super.configureDataFormat(dataFormat, camelContext); 255 256 if (nullValue != null) { 257 setProperty(camelContext, dataFormat, "nullValue", nullValue); 258 } 259 if (skipEmptyLines != null) { 260 setProperty(camelContext, dataFormat, "skipEmptyLines", skipEmptyLines); 261 } 262 if (ignoreTrailingWhitespaces != null) { 263 setProperty(camelContext, dataFormat, "ignoreTrailingWhitespaces", ignoreTrailingWhitespaces); 264 } 265 if (ignoreLeadingWhitespaces != null) { 266 setProperty(camelContext, dataFormat, "ignoreLeadingWhitespaces", ignoreLeadingWhitespaces); 267 } 268 if (headersDisabled != null) { 269 setProperty(camelContext, dataFormat, "headersDisabled", headersDisabled); 270 } 271 String[] validHeaderNames = getValidHeaderNames(); 272 if (validHeaderNames != null) { 273 setProperty(camelContext, dataFormat, "headers", validHeaderNames); 274 } 275 if (headerExtractionEnabled != null) { 276 setProperty(camelContext, dataFormat, "headerExtractionEnabled", headerExtractionEnabled); 277 } 278 if (numberOfRecordsToRead != null) { 279 setProperty(camelContext, dataFormat, "numberOfRecordsToRead", numberOfRecordsToRead); 280 } 281 if (emptyValue != null) { 282 setProperty(camelContext, dataFormat, "emptyValue", emptyValue); 283 } 284 if (lineSeparator != null) { 285 setProperty(camelContext, dataFormat, "lineSeparator", lineSeparator); 286 } 287 if (normalizedLineSeparator != null) { 288 setProperty(camelContext, dataFormat, "normalizedLineSeparator", singleCharOf("normalizedLineSeparator", normalizedLineSeparator)); 289 } 290 if (comment != null) { 291 setProperty(camelContext, dataFormat, "comment", singleCharOf("comment", comment)); 292 } 293 if (lazyLoad != null) { 294 setProperty(camelContext, dataFormat, "lazyLoad", lazyLoad); 295 } 296 if (asMap != null) { 297 setProperty(camelContext, dataFormat, "asMap", asMap); 298 } 299 } 300 301 protected static Character singleCharOf(String attributeName, String string) { 302 if (string.length() != 1) { 303 throw new IllegalArgumentException("Only one character must be defined for " + attributeName); 304 } 305 return string.charAt(0); 306 } 307 308 /** 309 * Gets only the headers with non-null and non-empty names. It returns {@code null} if there's no such headers. 310 * 311 * @return The headers with non-null and non-empty names 312 */ 313 private String[] getValidHeaderNames() { 314 if (headers == null) { 315 return null; 316 } 317 List<String> names = new ArrayList<String>(headers.size()); 318 for (UniVocityHeader header : headers) { 319 if (header.getName() != null && !header.getName().isEmpty()) { 320 names.add(header.getName()); 321 } 322 } 323 return names.isEmpty() ? null : names.toArray(new String[names.size()]); 324 } 325}