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