001/** 002 * Copyright (C) 2006-2022 Talend Inc. - www.talend.com 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 org.talend.sdk.component.api.record; 017 018import static java.util.Optional.ofNullable; 019 020import java.time.ZonedDateTime; 021import java.util.Collection; 022import java.util.Comparator; 023import java.util.Date; 024import java.util.List; 025import java.util.Optional; 026import java.util.OptionalDouble; 027import java.util.OptionalInt; 028import java.util.OptionalLong; 029 030import org.talend.sdk.component.api.record.Schema.Entry; 031 032public interface Record { 033 034 /** 035 * @return the schema of this record. 036 */ 037 Schema getSchema(); 038 039 /** 040 * Create a Builder with values of the record present in {@link Schema}. 041 * 042 * @param schema new schema 043 * @return a {@link Record.Builder} 044 */ 045 default Builder withNewSchema(Schema schema) { 046 throw new UnsupportedOperationException("#withNewSchema is not implemented"); 047 } 048 049 /** 050 * Access a record field value. 051 * 052 * IMPORTANT: it is always better to use the typed accessors and the optional flavor when the entry is nullable. 053 * 054 * @param expectedType the expected type for the column. 055 * @param name the name of the column. 056 * @param <T> the type of expectedType. 057 * @return the column value. 058 */ 059 <T> T get(Class<T> expectedType, String name); 060 061 default <T> T get(Class<T> expectedType, Schema.Entry entry) { 062 if (entry == null) { 063 return null; 064 } 065 return this.get(expectedType, entry.getName()); 066 } 067 068 /** 069 * See {@link Record#get(Class, String)}. 070 * 071 * @param name entry name. 072 * @return the value of the entry in this record. 073 */ 074 default String getString(final String name) { 075 return get(String.class, name); 076 } 077 078 /** 079 * See {@link Record#get(Class, String)}. 080 * 081 * @param name entry name. 082 * @return the value of the entry in this record. 083 */ 084 default int getInt(final String name) { 085 return get(Integer.class, name); 086 } 087 088 /** 089 * See {@link Record#get(Class, String)}. 090 * 091 * @param name entry name. 092 * @return the value of the entry in this record. 093 */ 094 default long getLong(final String name) { 095 return get(Long.class, name); 096 } 097 098 /** 099 * See {@link Record#get(Class, String)}. 100 * 101 * @param name entry name. 102 * @return the value of the entry in this record. 103 */ 104 default double getDouble(final String name) { 105 return get(Double.class, name); 106 } 107 108 /** 109 * See {@link Record#get(Class, String)}. 110 * 111 * @param name entry name. 112 * @return the value of the entry in this record. 113 */ 114 default float getFloat(final String name) { 115 return get(Float.class, name); 116 } 117 118 /** 119 * See {@link Record#get(Class, String)}. 120 * 121 * @param name entry name. 122 * @return the value of the entry in this record. 123 */ 124 default boolean getBoolean(final String name) { 125 return get(Boolean.class, name); 126 } 127 128 /** 129 * See {@link Record#get(Class, String)}. 130 * 131 * @param name entry name. 132 * @return the value of the entry in this record. 133 */ 134 default byte[] getBytes(final String name) { 135 return get(byte[].class, name); 136 } 137 138 /** 139 * See {@link Record#get(Class, String)}. 140 * 141 * @param name entry name. 142 * @return the value of the entry in this record. 143 */ 144 default Record getRecord(final String name) { 145 return get(Record.class, name); 146 } 147 148 /** 149 * See {@link Record#get(Class, String)}. 150 * 151 * @param type type of the elements of the collection. 152 * @param name entry name. 153 * @param <T> type of the collection elements. 154 * @return the value of the entry in this record. 155 */ 156 default <T> Collection<T> getArray(final Class<T> type, final String name) { 157 return get(Collection.class, name); 158 } 159 160 /** 161 * See {@link Record#get(Class, String)}. 162 * 163 * @param name entry name. 164 * @return the value of the entry in this record. 165 */ 166 default ZonedDateTime getDateTime(final String name) { 167 return get(ZonedDateTime.class, name); 168 } 169 170 /** 171 * See {@link Record#get(Class, String)}. 172 * 173 * @param type type of the elements of the collection. 174 * @param name entry name. 175 * @param <T> type of the collection elements. 176 * @return the value of the entry in this record. 177 */ 178 default <T> Optional<Collection<T>> getOptionalArray(final Class<T> type, final String name) { 179 final Collection<T> value = get(Collection.class, name); 180 return ofNullable(value); 181 } 182 183 /** 184 * See {@link Record#get(Class, String)}. 185 * 186 * @param name entry name. 187 * @return the value of the entry in this record. 188 */ 189 default Optional<ZonedDateTime> getOptionalDateTime(final String name) { 190 return ofNullable(get(ZonedDateTime.class, name)); 191 } 192 193 /** 194 * See {@link Record#get(Class, String)}. 195 * 196 * @param name entry name. 197 * @return the value of the entry in this record. 198 */ 199 default Optional<String> getOptionalString(final String name) { 200 return ofNullable(get(String.class, name)); 201 } 202 203 /** 204 * See {@link Record#get(Class, String)}. 205 * 206 * @param name entry name. 207 * @return the value of the entry in this record. 208 */ 209 default OptionalInt getOptionalInt(final String name) { 210 final Integer value = get(Integer.class, name); 211 return value == null ? OptionalInt.empty() : OptionalInt.of(value); 212 } 213 214 /** 215 * See {@link Record#get(Class, String)}. 216 * 217 * @param name entry name. 218 * @return the value of the entry in this record. 219 */ 220 default OptionalLong getOptionalLong(final String name) { 221 final Long value = get(Long.class, name); 222 return value == null ? OptionalLong.empty() : OptionalLong.of(value); 223 } 224 225 /** 226 * See {@link Record#get(Class, String)}. 227 * 228 * @param name entry name. 229 * @return the value of the entry in this record. 230 */ 231 default OptionalDouble getOptionalDouble(final String name) { 232 final Double value = get(Double.class, name); 233 return value == null ? OptionalDouble.empty() : OptionalDouble.of(value); 234 } 235 236 /** 237 * See {@link Record#get(Class, String)}. 238 * 239 * @param name entry name. 240 * @return the value of the entry in this record. 241 */ 242 default OptionalDouble getOptionalFloat(final String name) { 243 final Float value = get(Float.class, name); 244 return value == null ? OptionalDouble.empty() : OptionalDouble.of(value); 245 } 246 247 /** 248 * See {@link Record#get(Class, String)}. 249 * 250 * @param name entry name. 251 * @return the value of the entry in this record. 252 */ 253 default Optional<Boolean> getOptionalBoolean(final String name) { 254 return ofNullable(get(Boolean.class, name)); 255 } 256 257 /** 258 * See {@link Record#get(Class, String)}. 259 * 260 * @param name entry name. 261 * @return the value of the entry in this record. 262 */ 263 default Optional<byte[]> getOptionalBytes(final String name) { 264 return ofNullable(get(byte[].class, name)); 265 } 266 267 /** 268 * See {@link Record#get(Class, String)}. 269 * 270 * @param name entry name. 271 * @return the value of the entry in this record. 272 */ 273 default Optional<Record> getOptionalRecord(final String name) { 274 return ofNullable(get(Record.class, name)); 275 } 276 277 /** 278 * Allows to create a record with a fluent API. This is the unique recommended way to create a record. 279 */ 280 281 interface Builder { 282 283 Record build(); 284 285 Object getValue(String name); 286 287 List<Entry> getCurrentEntries(); 288 289 default Entry getEntry(final String name) { 290 return this.getCurrentEntries() 291 .stream() 292 .filter((Entry e) -> name.equals(e.getName())) 293 .findFirst() 294 .orElse(null); 295 } 296 297 /** 298 * Mark that next entry created {@code withXXXX()} will be before {@code entryName} in schema order. 299 * 300 * @see 301 * <ul> 302 * <li>{@link Schema#naturalOrder()}</li> 303 * <li>{@link Schema#getEntriesOrdered()}</li> 304 * <li>{@link Schema#getEntriesOrdered(Comparator)}</li> 305 * </ul> 306 * 307 * @param entryName target entry name. This entry <b>must</b> exist! 308 * 309 * @return this Builder 310 */ 311 default Builder before(String entryName) { 312 throw new UnsupportedOperationException("#before is not implemented"); 313 } 314 315 /** 316 * Mark that next entry created {@code withXXXX()} will be after {@code entryName} in schema order. 317 * 318 * @see 319 * <ul> 320 * <li>{@link Schema#naturalOrder()}</li> 321 * <li>{@link Schema#getEntriesOrdered()}</li> 322 * <li>{@link Schema#getEntriesOrdered(Comparator)}</li> 323 * </ul> 324 * 325 * @param entryName target entry name. This entry <b>must</b> exist! 326 * 327 * @return this Builder 328 */ 329 default Builder after(String entryName) { 330 throw new UnsupportedOperationException("#after"); 331 } 332 333 Builder removeEntry(Schema.Entry schemaEntry); 334 335 Builder updateEntryByName(String name, Schema.Entry schemaEntry); 336 337 Builder with(Schema.Entry entry, Object value); 338 339 Builder withString(String name, String value); 340 341 Builder withString(Schema.Entry entry, String value); 342 343 Builder withBytes(String name, byte[] value); 344 345 Builder withBytes(Schema.Entry entry, byte[] value); 346 347 Builder withDateTime(String name, Date value); 348 349 Builder withDateTime(Schema.Entry entry, Date value); 350 351 Builder withDateTime(String name, ZonedDateTime value); 352 353 Builder withDateTime(Schema.Entry entry, ZonedDateTime value); 354 355 Builder withTimestamp(String name, long value); 356 357 Builder withTimestamp(Schema.Entry entry, long value); 358 359 Builder withInt(String name, int value); 360 361 Builder withInt(Schema.Entry entry, int value); 362 363 Builder withLong(String name, long value); 364 365 Builder withLong(Schema.Entry entry, long value); 366 367 Builder withFloat(String name, float value); 368 369 Builder withFloat(Schema.Entry entry, float value); 370 371 Builder withDouble(String name, double value); 372 373 Builder withDouble(Schema.Entry entry, double value); 374 375 Builder withBoolean(String name, boolean value); 376 377 Builder withBoolean(Schema.Entry entry, boolean value); 378 379 Builder withRecord(Schema.Entry entry, Record value); 380 381 /** 382 * @since 1.1.6 383 * 384 * @param name entry name. 385 * @param value record value. 386 * @return this builder. 387 */ 388 Builder withRecord(String name, Record value); 389 390 <T> Builder withArray(Schema.Entry entry, Collection<T> values); 391 } 392}