Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion component-server-parent/component-server-model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Copyright (C) 2006-2025 Talend Inc. - www.talend.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.talend.sdk.component.server.front.model;

import java.beans.ConstructorProperties;
import java.util.LinkedHashMap;
import java.util.Map;

import lombok.Data;

@Data
public final class Entry {

private final String name;

private final String rawName;

private final Schema.Type type;

private final boolean nullable;

private final boolean metadata;

private final boolean errorCapable;

private final boolean valid;

private final Schema elementSchema;

private final String comment;

private final Map<String, String> props = new LinkedHashMap<>(0);

private final Object defaultValue;

@ConstructorProperties({ "name", "rawName", "type", "nullable", "metadata", "errorCapable",
"valid", "elementSchema", "comment", "props", "defaultValue" })
// Checkstyle off to let have 11 parameters to this constructor (normally 10 max)
// CHECKSTYLE:OFF
public Entry(

Check warning on line 53 in component-server-parent/component-server-model/src/main/java/org/talend/sdk/component/server/front/model/Entry.java

View check run for this annotation

sonar-eks / SonarQube Code Analysis

component-server-parent/component-server-model/src/main/java/org/talend/sdk/component/server/front/model/Entry.java#L53

Constructor has 11 parameters, which is greater than 7 authorized.
final String name,
final String rawName,
final Schema.Type type,
final boolean nullable,
final boolean metadata,
final boolean errorCapable,
final boolean valid,
final Schema elementSchema,
final String comment,
final Map<String, String> props,
final Object defaultValue) {
// CHECKSTYLE:ON
this.name = name;
this.rawName = rawName;
this.type = type;
this.nullable = nullable;
this.metadata = metadata;
this.errorCapable = errorCapable;
this.valid = valid;
this.elementSchema = elementSchema;
this.comment = comment;
if (props != null) {
this.props.putAll(props);
}
this.defaultValue = defaultValue;
}

private Object getInternalDefaultValue() {
return defaultValue;
}
Comment on lines +81 to +83
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getInternalDefaultValue method appears to be a simple getter for the defaultValue field. Consider removing this method and accessing the field directly in getDefaultValue() to reduce unnecessary indirection.

Copilot uses AI. Check for mistakes.

@SuppressWarnings("unchecked")
public <T> T getDefaultValue() {
if (defaultValue == null) {
return null;
}

return switch (this.getType()) {
case INT -> (T) ((Integer) ((Number) this.getInternalDefaultValue()).intValue());
case LONG -> (T) ((Long) ((Number) this.getInternalDefaultValue()).longValue());
case FLOAT -> (T) ((Float) ((Number) this.getInternalDefaultValue()).floatValue());
case DOUBLE -> (T) ((Double) ((Number) this.getInternalDefaultValue()).doubleValue());
default -> (T) this.getInternalDefaultValue();
};

}

/**
* * Returns the property value associated with the given key.
* * @param key the property key
* * @return the property value, or {@code null} if there is no mapping for the given key
*/
public String getOriginalFieldName() {
return rawName != null ? rawName : name;
}

public String getProp(final String key) {
return this.props.get(key);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Copyright (C) 2006-2025 Talend Inc. - www.talend.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.talend.sdk.component.server.front.model;

import java.beans.ConstructorProperties;
import java.math.BigDecimal;
import java.time.temporal.Temporal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import lombok.Data;

@Data
public final class Schema {

private final Type type;

private final Schema elementSchema;

private final List<Entry> entries;

private final List<Entry> metadata;

private final Map<String, String> props;

@ConstructorProperties({ "type", "elementSchema", "entries", "metadata", "props" })
public Schema(
final Type type,
final Schema elementSchema,
final List<Entry> entries,
final List<Entry> metadata,
final Map<String, String> props) {
this.type = type;
this.elementSchema = elementSchema;
this.entries = entries;
this.metadata = metadata;
this.props = props;
}

public String getProp(final String key) {
return this.props.get(key);
Comment on lines +55 to +56
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getProp method will throw NullPointerException if props is null. Add a null check before accessing props, or ensure props is never null in the constructor.

Copilot uses AI. Check for mistakes.
}

public enum Type {

RECORD(new Class<?>[] { Record.class }),
ARRAY(new Class<?>[] { Collection.class }),
STRING(new Class<?>[] { String.class, Object.class }),
BYTES(new Class<?>[] { byte[].class, Byte[].class }),
INT(new Class<?>[] { Integer.class }),
LONG(new Class<?>[] { Long.class }),
FLOAT(new Class<?>[] { Float.class }),
DOUBLE(new Class<?>[] { Double.class }),
BOOLEAN(new Class<?>[] { Boolean.class }),
DATETIME(new Class<?>[] { Long.class, Date.class, Temporal.class }),
DECIMAL(new Class<?>[] { BigDecimal.class });

/**
* All compatibles Java classes
*/
private final Class<?>[] classes;

Type(final Class<?>[] classes) {
this.classes = classes;
}

}
}
3 changes: 1 addition & 2 deletions component-server-parent/component-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
Expand Down Expand Up @@ -493,4 +492,4 @@
</build>
</profile>
</profiles>
</project>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* Copyright (C) 2006-2025 Talend Inc. - www.talend.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.talend.sdk.component.server.front;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;

import com.fasterxml.jackson.databind.ObjectMapper;

import org.junit.jupiter.api.Test;
import org.talend.sdk.component.api.record.SchemaProperty;
import org.talend.sdk.component.api.record.SchemaProperty.LogicalType;
import org.talend.sdk.component.runtime.record.RecordBuilderFactoryImpl;
import org.talend.sdk.component.server.front.model.Entry;
import org.talend.sdk.component.server.front.model.Schema;

/**
* Unit tests for {@link Entry}.
*/
class EntryTest {

private Entry createValidEntry() {
Map<String, String> props = new LinkedHashMap<>(0);
props.put("p1", "v1");
return new Entry("name", "raw", Schema.Type.STRING, true, false, true,
true, null, "comment", props, "default");
}

private Entry createEmptyEntry() {
Map<String, String> props = new LinkedHashMap<>(0);
props.put("p1", "v1");
return new Entry("name", null, Schema.Type.STRING, true, false, true,
true, null, null, props, null);
}

// ----------------------------------------------------------------------
// Builder
// ----------------------------------------------------------------------

@Test
void builderCreatesValidEntry() {
Entry entry = createValidEntry();

assertEquals("name", entry.getName());
assertEquals("raw", entry.getRawName());
assertEquals("raw", entry.getOriginalFieldName());
assertEquals(Schema.Type.STRING, entry.getType());
assertTrue(entry.isNullable());
assertFalse(entry.isMetadata());
assertTrue(entry.isErrorCapable());
assertTrue(entry.isValid());
assertEquals("comment", entry.getComment());
assertEquals("default", entry.getDefaultValue());
assertEquals("v1", entry.getProps().get("p1"));
}

// ----------------------------------------------------------------------
// Accessors
// ----------------------------------------------------------------------

@Test
void getDefaultValueIsTyped() {
Entry entry = createValidEntry();

String value = entry.getDefaultValue();
assertEquals("default", value);
}

@Test
void getDefaultValueEmpty() {
Entry entry = createEmptyEntry();

String value = entry.getDefaultValue();
assertNull(value);
}

@Test
void getPropReturnsProperty() {
Entry entry = createValidEntry();
assertEquals("v1", entry.getProp("p1"));
assertNull(entry.getProp("k1"));
}

// ----------------------------------------------------------------------
// JSON deserialization
// ----------------------------------------------------------------------

@Test
void deserializeEntryFromJson() throws Exception {
RecordBuilderFactoryImpl factory = new RecordBuilderFactoryImpl("test");
org.talend.sdk.component.api.record.Schema.Entry entryImpl = factory.newEntryBuilder()
.withName("éèfield")
.withLogicalType(LogicalType.UUID)
.withNullable(false)
.withMetadata(false)
.withErrorCapable(false)
.withComment("test comment")
.withProps(Map.of("p1", "v1"))
.withDefaultValue("defaultValue")
.build();

try (Jsonb jsonb = JsonbBuilder.create()) {
String json = jsonb.toJson(entryImpl);

ObjectMapper mapper = new ObjectMapper();
Entry entry = mapper.readValue(json, Entry.class);

assertEquals("_field", entry.getName());
assertEquals("éèfield", entry.getRawName());
assertEquals("éèfield", entry.getOriginalFieldName());
assertEquals(Schema.Type.STRING, entry.getType());
assertEquals(LogicalType.UUID.key(), entry.getProp(SchemaProperty.LOGICAL_TYPE));

assertFalse(entry.isNullable());
assertFalse(entry.isMetadata());
assertFalse(entry.isErrorCapable());
assertTrue(entry.isValid());

assertEquals("test comment", entry.getComment());
assertEquals("v1", entry.getProps().get("p1"));
assertEquals("defaultValue", entry.getDefaultValue());
}
}

}
Loading
Loading