001/**
002 * Copyright (C) 2006-2025 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.runtime.record;
017
018import static java.util.function.Function.identity;
019import static java.util.stream.Collectors.toMap;
020
021import java.io.ObjectStreamException;
022import java.io.Serializable;
023import java.util.Map;
024
025import org.talend.sdk.component.api.record.Record;
026import org.talend.sdk.component.api.record.Schema;
027import org.talend.sdk.component.api.service.record.RecordBuilderFactory;
028import org.talend.sdk.component.runtime.serialization.SerializableService;
029
030import lombok.Data;
031
032@Data
033public class RecordBuilderFactoryImpl implements RecordBuilderFactory, Serializable {
034
035    protected final String plugin;
036
037    @Override
038    public Schema.Builder newSchemaBuilder(final Schema.Type type) {
039        switch (type) {
040            case RECORD:
041            case ARRAY:
042                return new SchemaImpl.BuilderImpl().withType(type);
043            default:
044                return Schemas.valueOf(type.name());
045        }
046    }
047
048    @Override
049    public Schema.Builder newSchemaBuilder(final Schema schema) {
050        final Schema.Builder builder = newSchemaBuilder(schema.getType());
051        switch (schema.getType()) {
052            case RECORD:
053                schema.getAllEntries().forEach(builder::withEntry);
054                break;
055            case ARRAY:
056                builder.withElementSchema(schema.getElementSchema());
057                break;
058            default:
059        }
060        return builder;
061    }
062
063    @Override
064    public Record.Builder newRecordBuilder(final Schema schema, final Record record) {
065        final Record.Builder builder = newRecordBuilder(schema);
066        final Map<String, Schema.Entry> entriesIndex =
067                schema.getAllEntries().collect(toMap(Schema.Entry::getName, identity()));
068        record.getSchema().getAllEntries().filter(e -> entriesIndex.containsKey(e.getName())).forEach(entry -> {
069            switch (entry.getType()) {
070                case STRING:
071                    record
072                            .getOptionalString(entry.getName())
073                            .ifPresent(v -> builder.withString(entriesIndex.get(entry.getName()), v));
074                    break;
075                case LONG:
076                    record
077                            .getOptionalLong(entry.getName())
078                            .ifPresent(v -> builder.withLong(entriesIndex.get(entry.getName()), v));
079                    break;
080                case INT:
081                    record
082                            .getOptionalInt(entry.getName())
083                            .ifPresent(v -> builder.withInt(entriesIndex.get(entry.getName()), v));
084                    break;
085                case DOUBLE:
086                    record
087                            .getOptionalDouble(entry.getName())
088                            .ifPresent(v -> builder.withDouble(entriesIndex.get(entry.getName()), v));
089                    break;
090                case FLOAT:
091                    record
092                            .getOptionalFloat(entry.getName())
093                            .ifPresent(v -> builder.withFloat(entriesIndex.get(entry.getName()), (float) v));
094                    break;
095                case BOOLEAN:
096                    record
097                            .getOptionalBoolean(entry.getName())
098                            .ifPresent(v -> builder.withBoolean(entriesIndex.get(entry.getName()), v));
099                    break;
100                case BYTES:
101                    record
102                            .getOptionalBytes(entry.getName())
103                            .ifPresent(v -> builder.withBytes(entriesIndex.get(entry.getName()), v));
104                    break;
105                case DATETIME:
106                    record
107                            .getOptionalDateTime(entry.getName())
108                            .ifPresent(v -> builder.withDateTime(entriesIndex.get(entry.getName()), v));
109                    break;
110                case DECIMAL:
111                    record
112                            .getOptionalDecimal(entry.getName())
113                            .ifPresent(v -> builder.withDecimal(entriesIndex.get(entry.getName()), v));
114                    break;
115                case RECORD:
116                    record
117                            .getOptionalRecord(entry.getName())
118                            .ifPresent(v -> builder.withRecord(entriesIndex.get(entry.getName()), v));
119                    break;
120                case ARRAY:
121                    record
122                            .getOptionalArray(Object.class, entry.getName())
123                            .ifPresent(v -> builder.withArray(entriesIndex.get(entry.getName()), v));
124                    break;
125                default:
126                    throw new IllegalArgumentException("Unsupported entry type: " + entry);
127            }
128        });
129        return builder;
130    }
131
132    @Override
133    public Record.Builder newRecordBuilder(final Schema schema) {
134        return new RecordImpl.BuilderImpl(schema);
135    }
136
137    @Override
138    public Record.Builder newRecordBuilder() {
139        return new RecordImpl.BuilderImpl();
140    }
141
142    @Override
143    public Schema.Entry.Builder newEntryBuilder() {
144        return new SchemaImpl.EntryImpl.BuilderImpl();
145    }
146
147    Object writeReplace() throws ObjectStreamException {
148        return new SerializableService(plugin, RecordBuilderFactory.class.getName());
149    }
150}