Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#20: Refactored ColumnAdapterNotes. #25

Merged
merged 3 commits into from
Jan 31, 2020
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,108 +2,44 @@

import java.util.Objects;

import javax.json.*;

import com.exasol.adapter.AdapterException;
import com.exasol.utils.JsonHelper;

/**
* Serializes and deserializes the column adapter notes specific to the JDBC Adapter.
* Holds the column adapter notes.
*/
public final class ColumnAdapterNotes {
private static final String TYPE_NAME = "typeName";
private static final String JDBC_DATA_TYPE = "jdbcDataType";
private final int jdbcDataType;
private final String typeName;

/**
* Create a new instance of the {@link ColumnAdapterNotes}.
*
* @param jdbcDataType JDBC data type in int format
* @param typeName name of the data type
* @param jdbcDataType JDBC data type number
*/
public ColumnAdapterNotes(final int jdbcDataType, final String typeName) {
public ColumnAdapterNotes(final int jdbcDataType) {
this.jdbcDataType = jdbcDataType;
this.typeName = typeName;
}

/**
* Get JDBC data type.
*
* @return JDBC data type as an int
*
* @return JDBC data type as a number
*/
public int getJdbcDataType() {
return this.jdbcDataType;
}

/**
* Get JDBC type name.
*
* @return JDBC type name as a string
*/
public String getTypeName() {
return this.typeName;
}

/**
* Serialized column adapter notes.
*
* @param notes column adapter notes
* @return serialized column adapter notes
*/
public static String serialize(final ColumnAdapterNotes notes) {
final JsonBuilderFactory factory = JsonHelper.getBuilderFactory();
final JsonObjectBuilder builder = factory.createObjectBuilder().add(JDBC_DATA_TYPE, notes.getJdbcDataType())
.add(TYPE_NAME, notes.getTypeName());
return builder.build().toString();
}

/**
* Deserialize column adapter notes.
*
* @param columnAdapterNotes column adapter notes
* @param columnName column name
* @return deserialized column adapter notes
* @throws AdapterException if column adapter notes are empty or null
*/
public static ColumnAdapterNotes deserialize(final String columnAdapterNotes, final String columnName)
throws AdapterException {
if ((columnAdapterNotes == null) || columnAdapterNotes.isEmpty()) {
throw new AdapterException("The adapternotes field of column " + columnName
+ " is empty or null. Please refresh the virtual schema.");
}
final JsonObject root;
try {
root = JsonHelper.getJsonObject(columnAdapterNotes);
} catch (final Exception exception) {
throw new AdapterException("Can not get the json object for column notes of column " + columnName
+ ". Please refresh the virtual schema. Caused by: " + exception.getMessage(), exception);
}
checkKey(root, JDBC_DATA_TYPE, columnName);
checkKey(root, TYPE_NAME, columnName);
return new ColumnAdapterNotes(root.getInt(JDBC_DATA_TYPE), root.getString(TYPE_NAME));
}

private static void checkKey(final JsonObject root, final String key, final String columnName)
throws AdapterException {
if (!root.containsKey(key)) {
throw new AdapterException("Adapter notes of column " + columnName + " don't have the key " + key
+ ". Please refresh the virtual schema");
}
}

@Override
public boolean equals(final Object other) {
if (this == other)
if (this == other) {
return true;
if (!(other instanceof ColumnAdapterNotes))
}
if (!(other instanceof ColumnAdapterNotes)) {
return false;
}
final ColumnAdapterNotes that = (ColumnAdapterNotes) other;
return this.jdbcDataType == that.jdbcDataType && Objects.equals(this.typeName, that.typeName);
return this.jdbcDataType == that.jdbcDataType;
}

@Override
public int hashCode() {
return Objects.hash(this.jdbcDataType, this.typeName);
return Objects.hash(this.jdbcDataType);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.exasol.adapter.adapternotes;

import javax.json.*;

import com.exasol.adapter.AdapterException;
import com.exasol.utils.JsonHelper;

/**
* Converts column adapter Notes into JSON format and back.
*/
public final class ColumnAdapterNotesJsonConverter {
private static final ColumnAdapterNotesJsonConverter COLUMN_ADAPTER_NOTES_JSON_CONVERTER = new ColumnAdapterNotesJsonConverter();

/**
* Returns instance of {@link ColumnAdapterNotesJsonConverter} singleton class.
*
* @return {@link ColumnAdapterNotesJsonConverter} instance
*/
public static ColumnAdapterNotesJsonConverter getInstance() {
return COLUMN_ADAPTER_NOTES_JSON_CONVERTER;
}

private ColumnAdapterNotesJsonConverter() {
// intentionally left blank
}

/**
* Converts column adapter notes into a JSON format.
*
* @param columnAdapterNotes column adapter notes to be converted
* @return string representation of a JSON Object
*/
public String convertToJson(final ColumnAdapterNotes columnAdapterNotes) {
final JsonBuilderFactory factory = JsonHelper.getBuilderFactory();
final JsonObjectBuilder builder = factory.createObjectBuilder().add("jdbcDataType",
columnAdapterNotes.getJdbcDataType());
return builder.build().toString();
}

/**
* Converts JSON representation of column adapter notes into instance of {@link ColumnAdapterNotes} class.
*
* @param adapterNotes JSON representation of schema adapter notes
* @param columnName name of the column
* @return instance of {@link ColumnAdapterNotes}
* @throws AdapterException if the adapter notes are missing or cannot be parsed
*/
public ColumnAdapterNotes convertFromJsonToColumnAdapterNotes(final String adapterNotes, final String columnName)
throws AdapterException {
if ((adapterNotes == null) || adapterNotes.isEmpty()) {
throw new AdapterException("Adapter notes for column " + columnName + " are empty or NULL. " //
+ "Please refresh the virtual schema.");
}
final JsonObject root;
try {
root = JsonHelper.getJsonObject(adapterNotes);
} catch (final Exception exception) {
throw new AdapterException("Could not parse the column adapter notes of column \"" + columnName + "\"." //
+ "Please refresh the virtual schema.", exception);
}
return new ColumnAdapterNotes(root.getInt("jdbcDataType"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import java.util.Objects;

/**
* Holds the schema adapter notes specific to the JDBC Adapter. Also includes functionality to serialize and
* deserialize.
* Holds the schema adapter notes specific to the JDBC Adapter.
*/
public final class SchemaAdapterNotes {
private final String catalogSeparator;
Expand Down Expand Up @@ -159,22 +158,22 @@ public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
final SchemaAdapterNotes that = (SchemaAdapterNotes) o;
return this.storesLowerCaseIdentifiers == that.storesLowerCaseIdentifiers
&& this.storesUpperCaseIdentifiers == that.storesUpperCaseIdentifiers
&& this.storesMixedCaseIdentifiers == that.storesMixedCaseIdentifiers
&& this.supportsMixedCaseIdentifiers == that.supportsMixedCaseIdentifiers
&& this.storesLowerCaseQuotedIdentifiers == that.storesLowerCaseQuotedIdentifiers
&& this.storesUpperCaseQuotedIdentifiers == that.storesUpperCaseQuotedIdentifiers
&& this.storesMixedCaseQuotedIdentifiers == that.storesMixedCaseQuotedIdentifiers
&& this.supportsMixedCaseQuotedIdentifiers == that.supportsMixedCaseQuotedIdentifiers
&& this.areNullsSortedAtEnd == that.areNullsSortedAtEnd
&& this.areNullsSortedAtStart == that.areNullsSortedAtStart
&& this.areNullsSortedHigh == that.areNullsSortedHigh
&& this.areNullsSortedLow == that.areNullsSortedLow
return (this.storesLowerCaseIdentifiers == that.storesLowerCaseIdentifiers)
&& (this.storesUpperCaseIdentifiers == that.storesUpperCaseIdentifiers)
&& (this.storesMixedCaseIdentifiers == that.storesMixedCaseIdentifiers)
&& (this.supportsMixedCaseIdentifiers == that.supportsMixedCaseIdentifiers)
&& (this.storesLowerCaseQuotedIdentifiers == that.storesLowerCaseQuotedIdentifiers)
&& (this.storesUpperCaseQuotedIdentifiers == that.storesUpperCaseQuotedIdentifiers)
&& (this.storesMixedCaseQuotedIdentifiers == that.storesMixedCaseQuotedIdentifiers)
&& (this.supportsMixedCaseQuotedIdentifiers == that.supportsMixedCaseQuotedIdentifiers)
&& (this.areNullsSortedAtEnd == that.areNullsSortedAtEnd)
&& (this.areNullsSortedAtStart == that.areNullsSortedAtStart)
&& (this.areNullsSortedHigh == that.areNullsSortedHigh)
&& (this.areNullsSortedLow == that.areNullsSortedLow)
&& Objects.equals(this.catalogSeparator, that.catalogSeparator)
&& Objects.equals(this.identifierQuoteString, that.identifierQuoteString);
}
Expand Down Expand Up @@ -393,4 +392,4 @@ public SchemaAdapterNotes build() {
return new SchemaAdapterNotes(this);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private SchemaAdapterNotesJsonConverter() {
/**
* Converts schema adapter notes into a JSON format.
*
* @param schemaAdapterNotes instance
* @param schemaAdapterNotes schema adapter notes to be converted
* @return string representation of a JSON Object
*/
public String convertToJson(final SchemaAdapterNotes schemaAdapterNotes) {
Expand All @@ -65,27 +65,25 @@ public String convertToJson(final SchemaAdapterNotes schemaAdapterNotes) {
}

/**
* Converts JSON representation of schema adapter notes into instance of {@link SchemaAdapterNotesJsonConverter}
* class.
* Converts JSON representation of schema adapter notes into instance of {@link SchemaAdapterNotes} class.
*
* @param adapterNotes JSON representation of schema adapter notes
* @param schemaName name of virtual schema
* @return instance of {@link SchemaAdapterNotesJsonConverter}
* @return instance of {@link SchemaAdapterNotes}
* @throws AdapterException if the adapter notes are missing or cannot be parsed
*/
public SchemaAdapterNotes convertFromJsonToSchemaAdapterNotes(final String adapterNotes, final String schemaName)
throws AdapterException {
if ((adapterNotes == null) || adapterNotes.isEmpty()) {
throw new AdapterException("Adapter notes for virtual schema " + schemaName + " are empty or null. " //
+ "Please refresh the virtual schema");
throw new AdapterException("Adapter notes for virtual schema " + schemaName + " are empty or NULL. " //
+ "Please refresh the virtual schema.");
}
final JsonObject root;
try {
root = JsonHelper.getJsonObject(adapterNotes);
} catch (final Exception ex) {
throw new AdapterException(
"Could not parse the json which is expected to be stored in the adapter notes of virtual schema "
+ schemaName + ". Please refresh the virtual schema");
} catch (final Exception exception) {
throw new AdapterException("Could not parse the schema adapter notes of virtual schema \"" + schemaName
+ "\". Please refresh the virtual schema.", exception);
}
checkKey(root, CATALOG_SEPARATOR, schemaName);
checkKey(root, IDENTIFIER_QUOTE_STRING, schemaName);
Expand Down Expand Up @@ -126,4 +124,4 @@ private static void checkKey(final JsonObject root, final String key, final Stri
+ ". Please refresh the virtual schema");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import com.exasol.adapter.AdapterProperties;
import com.exasol.adapter.adapternotes.ColumnAdapterNotes;
import com.exasol.adapter.adapternotes.ColumnAdapterNotesJsonConverter;
import com.exasol.adapter.dialects.IdentifierConverter;
import com.exasol.adapter.metadata.ColumnMetadata;
import com.exasol.adapter.metadata.DataType;
Expand Down Expand Up @@ -91,8 +92,8 @@ private ColumnMetadata mapColumn(final ResultSet remoteColumn) throws SQLExcepti
final JdbcTypeDescription jdbcTypeDescription = readJdbcTypeDescription(remoteColumn);
final String columnName = readColumnName(remoteColumn);
final String originalTypeName = readColumnTypeName(remoteColumn);
final String adapterNotes = ColumnAdapterNotes
.serialize(new ColumnAdapterNotes(jdbcTypeDescription.getJdbcType(), originalTypeName));
final String adapterNotes = ColumnAdapterNotesJsonConverter.getInstance()
.convertToJson(new ColumnAdapterNotes(jdbcTypeDescription.getJdbcType()));
final DataType exasolType = mapJdbcType(jdbcTypeDescription);
return ColumnMetadata.builder() //
.name(columnName) //
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.exasol.adapter.adapternotes;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.sql.Types;

import org.json.JSONException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;

import com.exasol.adapter.AdapterException;

class ColumnAdapterNotesJsonConverterTest {
private static final String JDBC_DATA_TYPE = "jdbcDataType";
private ColumnAdapterNotesJsonConverter converter;

@BeforeEach
void beforeEach() {
this.converter = ColumnAdapterNotesJsonConverter.getInstance();
}

@Test
void testConvertToJson() throws JSONException {
final int expectedType = Types.DATE;
final ColumnAdapterNotes adapterNotes = new ColumnAdapterNotes(expectedType);
JSONAssert.assertEquals("{\"" + JDBC_DATA_TYPE + "\":" + expectedType + "}",
this.converter.convertToJson(adapterNotes), false);
}

@Test
void testConvertFromJsonToColumnAdapterNotes() throws AdapterException {
final int expectedType = Types.VARCHAR;
final String adapterNotesAsJson = "{\"" + JDBC_DATA_TYPE + "\":" + expectedType + "}";
final ColumnAdapterNotes expectedAdapterNotes = new ColumnAdapterNotes(expectedType);
assertThat(this.converter.convertFromJsonToColumnAdapterNotes(adapterNotesAsJson, "C1"),
Copy link
Contributor

Choose a reason for hiding this comment

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

We usually use JSONAssert.assertEquals, don't we?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Depends on the direction. This is reverse (i.e. deserialization). JSONAssert does not help here.

equalTo(expectedAdapterNotes));
}

@Test
void testConvertFromJsonToColumnAdapterNotesThrowsExceptionWhenAdapterNotesAreNull() {
assertThrows(AdapterException.class, () -> this.converter.convertFromJsonToColumnAdapterNotes(null, ""));
}

@Test
void testConvertFromJsonToColumnAdapterNotesThrowsExceptionWithEmptyAdapterNotes() {
assertThrows(AdapterException.class, () -> this.converter.convertFromJsonToColumnAdapterNotes("", ""));
}

@Test
void testconvertFromJsonToColumnAdapterNotesThrowsExceptionWithWrongAdapterNotes() {
assertThrows(AdapterException.class, () -> this.converter.convertFromJsonToColumnAdapterNotes("testNotes", ""));
}
}
Loading