Skip to content

Commit

Permalink
JSON data sample for logicalTypes
Browse files Browse the repository at this point in the history
  • Loading branch information
pdesmarets committed Oct 30, 2019
1 parent 28f69c6 commit f763f39
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 49 deletions.
106 changes: 106 additions & 0 deletions adapter/0.1.32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* Copyright © 2016-2019 by IntegrIT S.A. dba Hackolade. All rights reserved.
*
* The copyright to the computer software herein is the property of IntegrIT S.A.
* The software may be used and/or copied only with the written permission of
* IntegrIT S.A. or in accordance with the terms and conditions stipulated in
* the agreement/contract under which the software has been supplied.
*
* {
* "add": {
* "entity": [<names of new property>],
* "container": [<names of new property>],
* "model": [<names of new property>],
* "view": [<names of new property>],
* "field": {
* "<type>": [<names of new property>]
* }
* },
* "delete": {
* "entity": [<names of new property>],
* "container": [<names of new property>],
* "model": [<names of new property>],
* "view": [<names of new property>],
* "field": {
* "<type>": [<names of new property>]
* }
* },
* "modify": {
* "entity": [
* {
* "from": { <properties that identify record> },
* "to": { <properties that need to be changed> }
* }
* ],
* "container": [],
* "model": [],
* "view": [],
* "field": []
* },
* }
*/

{
"add": {
},
"modify": {
"field": [
{
"from": {
"logicalType": "decimal"
},
"to": {
"subtype": "decimal"
}
},
{
"from": {
"logicalType": "duration"
},
"to": {
"subtype": "duration"
}
}
],
"multipleTypes": [
{
"from": {
"logicalType": "decimal"
},
"to": {
"subtype": "decimal"
}
},
{
"from": {
"logicalType": "duration"
},
"to": {
"subtype": "duration"
}
}
]
},
"delete": {
"field": [
{
"key": "logicalType",
"value": "duration"
},
{
"key": "logicalType",
"value": "decimal"
}
],
"multipleTypes": [
{
"key": "logicalType",
"value": "duration"
},
{
"key": "logicalType",
"value": "decimal"
}
]
}
}
94 changes: 76 additions & 18 deletions forward_engineering/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const _ = require('lodash');
const validationHelper = require('./validationHelper');
const mapJsonSchema = require('../reverse_engineering/helpers/mapJsonSchema');

const ADDITIONAL_PROPS = ['doc', 'order', 'aliases', 'symbols', 'namespace', 'size', 'durationSize', 'default'];
const ADDITIONAL_PROPS = ['doc', 'order', 'aliases', 'symbols', 'namespace', 'size', 'durationSize', 'default', 'precision', 'scale'];
const ADDITIONAL_CHOICE_META_PROPS = ADDITIONAL_PROPS.concat('index');
const PRIMITIVE_FIELD_ATTRIBUTES = ['order', 'logicalType', 'precision', 'scale', 'aliases'];
const DEFAULT_TYPE = 'string';
Expand Down Expand Up @@ -168,6 +168,10 @@ const handleRecursiveSchema = (schema, avroSchema, parentSchema = {}, udt) => {
handleChoice(schema, 'allOf', udt);
}
schema.type = schema.type || getTypeFromReference(schema);
if (schema.subtype && schema.type !== 'map') {
schema.logicalType = schema.subtype;
delete schema.subtype;
}

for (let prop in schema) {
switch (prop) {
Expand All @@ -194,6 +198,45 @@ const handleRecursiveSchema = (schema, avroSchema, parentSchema = {}, udt) => {
return;
};

const handleMergedChoice = (schema, udt) => {
const meta = schema.allOf_meta;
const separateChoices = meta.reduce((choices, meta) => {
const items = schema.allOf.filter(item => {
const ids = _.get(meta, 'ids', []);

return ids.includes(item.GUID);
});
const type = _.get(meta, 'choice');
if (!type || type === 'allOf') {
return choices.concat({ items, type: 'allOf', meta });
}

const choiceItems = _.first(items)[type];

return choices.concat({ items: choiceItems, type, meta });


}, []);

const newSchema = separateChoices.reduce((updatedSchema, choiceData) => {
const choiceType = choiceData.type;
const schemaWithChoice = Object.assign({}, removeChoices(updatedSchema), {
[choiceType]: choiceData.items,
[`${choiceType}_meta`]: choiceData.meta
});

handleChoice(schemaWithChoice, choiceType, udt);

return schemaWithChoice;
}, schema);

return Object.assign(schema, newSchema);
};

const removeChoices = schema => _.omit(schema, [
'oneOf', 'oneOf_meta', 'allOf', 'allOf_meta', 'anyOf', 'anyOf_meta', 'not', 'not_meta'
]);

const handleChoice = (schema, choice, udt) => {
const convertDefaultMetaFieldType = (type, value) => {
if (type === 'null' && value === 'null') {
Expand All @@ -207,6 +250,9 @@ const handleChoice = (schema, choice, udt) => {
};

const choiceRawMeta = schema[`${choice}_meta`];
if (_.isArray(choiceRawMeta)) {
return handleMergedChoice(schema, udt);
}

let choiceMeta = {};
let allSubSchemaFields = [];
Expand Down Expand Up @@ -245,11 +291,15 @@ const handleChoice = (schema, choice, udt) => {
allSubSchemaFields.forEach(field => {
const fieldName = choiceMeta.name || field.name;
if (!multipleFieldsHash[fieldName]) {
if (choiceMeta.default) {
if (!_.isUndefined(choiceMeta.default)) {
choiceMeta.default = convertDefaultMetaFieldType(field.type, choiceMeta.default);
}

multipleFieldsHash[fieldName] = Object.assign({}, field.choiceMeta, {
if (choiceMeta.default === '') {
delete choiceMeta.default;
}

multipleFieldsHash[fieldName] = Object.assign({}, choiceMeta, {
name: fieldName,
type: [],
choiceMeta
Expand Down Expand Up @@ -288,15 +338,15 @@ const handleChoice = (schema, choice, udt) => {
schema.properties = addPropertiesFromChoices(schema.properties, multipleFieldsHash);
};

const getChoiceIndex = choice => _.get(choice, 'choiceMeta.index', choice.index);
const getChoiceIndex = choice => _.get(choice, 'choiceMeta.index');

const addPropertiesFromChoices = (properties, choiceProperties) => {
if (_.isEmpty(choiceProperties)) {
return properties;
}

const sortedKeys = Object.keys(choiceProperties).sort((a, b) => {
getChoiceIndex(a) - getChoiceIndex(b)
return getChoiceIndex(a) - getChoiceIndex(b)
});

return sortedKeys.reduce((sortedProperties, choicePropertyKey) => {
Expand All @@ -315,8 +365,16 @@ const addPropertiesFromChoices = (properties, choiceProperties) => {
});
}

return Object.keys(sortedProperties).reduce((result, propertyKey, index) => {
if (index !== choicePropertyIndex || result[choicePropertyKey]) {
return Object.keys(sortedProperties).reduce((result, propertyKey, index, keys) => {
const currentIndex = getChoiceIndex(sortedProperties[propertyKey]);
const hasSameChoiceIndex = !_.isUndefined(currentIndex) && currentIndex <= choicePropertyIndex;
if (index < choicePropertyIndex || result[choicePropertyKey] || hasSameChoiceIndex) {
if (!result[choicePropertyKey] && keys.length === index + 1) {
return Object.assign({}, result, {
[propertyKey] : sortedProperties[propertyKey],
[choicePropertyKey]: choiceProperty,
});
}
return Object.assign({}, result, {
[propertyKey] : sortedProperties[propertyKey]
});
Expand All @@ -326,7 +384,7 @@ const addPropertiesFromChoices = (properties, choiceProperties) => {
[choicePropertyKey]: choiceProperty,
[propertyKey] : sortedProperties[propertyKey]
});
}, {})
}, {});
}, properties || {});
};

Expand Down Expand Up @@ -583,12 +641,6 @@ const handleItems = (schema, avroSchema, udt) => {
}
};

const uniqBy = (arr, prop) => {
return arr.map(function(e) { return e[prop]; }).filter(function(e,i,a){
return i === a.indexOf(e);
});
};

const handleOtherProps = (schema, prop, avroSchema) => {
if (prop === 'default') {
avroSchema[prop] = getDefault(schema.type, schema[prop]);
Expand Down Expand Up @@ -714,14 +766,15 @@ const getTargetFieldLevelPropertyNames = (type, data) => {
return fieldLevelConfig.structure[type].filter(property => {
if (typeof property === 'object' && property.isTargetProperty) {
if (property.dependency) {
return (data[property.dependency.key] == property.dependency.value);
const dependencyKey = resolveKey(type, property.dependency.key);
return (data[dependencyKey] == property.dependency.value);
} else {
return true;
}
}

return false;
}).map(property => property.propertyKeyword);
}).map(property => resolveKey(type, property));
};

const getAllowedPropertyNames = (type, data) => {
Expand All @@ -737,10 +790,15 @@ const getAllowedPropertyNames = (type, data) => {
return true;
}

return (data[property.dependency.key] === property.dependency.value);
}).map(property => _.isString(property) ? property : property.propertyKeyword);
const dependencyKey = resolveKey(type, property.dependency.key);

return (data[dependencyKey] === property.dependency.value);
}).map(property => _.isString(property) ? property : property.propertyKeyword)
.map(name => resolveKey(type, name));
};

const resolveKey = (type, key) => (key === 'subtype' && type !== 'map') ? 'logicalType' : key;

const handleTargetProperties = (schema, avroSchema) => {
if (schema.type) {
const targetProperties = getTargetFieldLevelPropertyNames(schema.type, schema);
Expand Down
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Avro",
"version": "0.1.31",
"version": "0.1.32",
"versionDate": "2019-10-17",
"author": "hackolade",
"engines": {
Expand All @@ -25,7 +25,17 @@
"bytes": {
"dependencies": [{
"dependency": {
"key": "logicalType",
"key": "subtype",
"value": "decimal"
},
"value": "number"
}],
"defaultValue": "string"
},
"fixed": {
"dependencies": [{
"dependency": {
"key": "subtype",
"value": "decimal"
},
"value": "number"
Expand Down
4 changes: 1 addition & 3 deletions properties_pane/defaultData.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
},
"field": {
"name": "New_field",
"required": true,
"size": 1,
"durationSize": 1
"required": true
},
"patternField": {
"name": "^[a-zA-Z0-9_.-]{20}$"
Expand Down
Loading

0 comments on commit f763f39

Please sign in to comment.