Skip to content
Snippets Groups Projects
Commit f6f3f6df authored by Alexander Rose's avatar Alexander Rose
Browse files

schema generation tweaks, get category metadata

parent 995919a3
Branches
Tags
No related merge requests found
...@@ -130,6 +130,7 @@ function getSubCategory (d: Data.CifFrame, ctx: FrameData): string|undefined { ...@@ -130,6 +130,7 @@ function getSubCategory (d: Data.CifFrame, ctx: FrameData): string|undefined {
function getDescription (d: Data.CifFrame, ctx: FrameData): string|undefined { function getDescription (d: Data.CifFrame, ctx: FrameData): string|undefined {
const value = getField('item_description', 'description', d, ctx) const value = getField('item_description', 'description', d, ctx)
if (value) { if (value) {
// trim (after newlines) and remove references to square brackets
return value.str(0).trim() return value.str(0).trim()
.replace(/(\r\n|\r|\n)([ \t]+)/g, '\n') .replace(/(\r\n|\r|\n)([ \t]+)/g, '\n')
.replace(/(\[[1-3]\])+ element/, 'elements') .replace(/(\[[1-3]\])+ element/, 'elements')
...@@ -195,6 +196,40 @@ export function generateSchema (frames: CifFrame[]) { ...@@ -195,6 +196,40 @@ export function generateSchema (frames: CifFrame[]) {
const links: FrameLinks = {} const links: FrameLinks = {}
const ctx = { categories, links } const ctx = { categories, links }
// get category metadata
frames.forEach(d => {
if (d.header[0] === '_') return
const categoryKeyNames = new Set<string>()
const categoryKey = d.categories['category_key']
if (categoryKey) {
const categoryKey_names = categoryKey.getField('name')
if (categoryKey_names) {
for (let i = 0, il = categoryKey_names.rowCount; i < il; ++i) {
categoryKeyNames.add(categoryKey_names.str(i))
}
}
}
let description = ''
const category = d.categories['category']
if (category) {
const category_description = category.getField('description')
if (category_description) {
description = category_description.str(0).trim()
.replace(/(\r\n|\r|\n)([ \t]+)/g, '\n') // remove padding after newlines
} else {
console.log(`no description given for category '${category}'`)
}
}
if (categoryKeyNames.size === 0) {
console.log(`no key given for category '${category}'`)
}
schema[d.header] = { description, key: categoryKeyNames, columns: {} }
// console.log('++++++++++++++++++++++++++++++++++++++++++')
// console.log('name', d.header)
// console.log('desc', description)
// console.log('key', categoryKeyNames)
})
// build list of links between categories // build list of links between categories
frames.forEach(d => { frames.forEach(d => {
if (d.header[0] !== '_') return if (d.header[0] !== '_') return
...@@ -216,6 +251,7 @@ export function generateSchema (frames: CifFrame[]) { ...@@ -216,6 +251,7 @@ export function generateSchema (frames: CifFrame[]) {
} }
}) })
// get field data
Object.keys(categories).forEach(fullName => { Object.keys(categories).forEach(fullName => {
const d = categories[fullName] const d = categories[fullName]
if (!d) { if (!d) {
...@@ -226,10 +262,15 @@ export function generateSchema (frames: CifFrame[]) { ...@@ -226,10 +262,15 @@ export function generateSchema (frames: CifFrame[]) {
const itemName = d.header.substring(d.header.indexOf('.') + 1) const itemName = d.header.substring(d.header.indexOf('.') + 1)
let fields: { [k: string]: Column } let fields: { [k: string]: Column }
if (categoryName in schema) { if (categoryName in schema) {
fields = schema[categoryName] fields = schema[categoryName].columns
} else { } else {
console.log(`category '${categoryName}' has no metadata`)
fields = {} fields = {}
schema[categoryName] = fields schema[categoryName] = {
description: '',
key: new Set(),
columns: fields
}
} }
const description = getDescription(d, ctx) || '' const description = getDescription(d, ctx) || ''
......
...@@ -18,17 +18,7 @@ function header (name: string, info: string, importDatabasePath = 'mol-data/db') ...@@ -18,17 +18,7 @@ function header (name: string, info: string, importDatabasePath = 'mol-data/db')
import { Database, Column } from '${importDatabasePath}' import { Database, Column } from '${importDatabasePath}'
import Schema = Column.Schema import Schema = Column.Schema`
const str = Schema.str;
const int = Schema.int;
const float = Schema.float;
const coord = Schema.coord;
const Aliased = Schema.Aliased;
const Matrix = Schema.Matrix;
const Vector = Schema.Vector;
const List = Schema.List;`
} }
function footer (name: string) { function footer (name: string) {
...@@ -37,6 +27,32 @@ export type ${name}_Schema = typeof ${name}_Schema; ...@@ -37,6 +27,32 @@ export type ${name}_Schema = typeof ${name}_Schema;
export interface ${name}_Database extends Database<${name}_Schema> {}` export interface ${name}_Database extends Database<${name}_Schema> {}`
} }
function getTypeShorthands(schema: Database, fields?: Filter) {
const types = new Set<string>()
Object.keys(schema).forEach(table => {
if (fields && !fields[table]) return
const { columns} = schema[table]
Object.keys(columns).forEach(columnName => {
if (fields && !fields[table][columnName]) return
types.add(schema[table].columns[columnName].type)
})
})
const shorthands: string[] = []
types.forEach(type => {
switch (type) {
case 'str': shorthands.push('const str = Schema.str;'); break
case 'int': shorthands.push('const int = Schema.int;'); break
case 'float': shorthands.push('const float = Schema.float;'); break
case 'coord': shorthands.push('const coord = Schema.coord;'); break
case 'enum': shorthands.push('const Aliased = Schema.Aliased;'); break
case 'matrix': shorthands.push('const Matrix = Schema.Matrix;'); break
case 'vector': shorthands.push('const Vector = Schema.Vector;'); break
case 'list': shorthands.push('const List = Schema.List;'); break
}
})
return shorthands.join('\n')
}
function getTypeDef(c: Column): string { function getTypeDef(c: Column): string {
switch (c.type) { switch (c.type) {
case 'str': return 'str' case 'str': return 'str'
...@@ -63,27 +79,34 @@ function getTypeDef(c: Column): string { ...@@ -63,27 +79,34 @@ function getTypeDef(c: Column): string {
const reSafePropertyName = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/ const reSafePropertyName = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/
function safePropertyString(name: string) { return name.match(reSafePropertyName) ? name : `'${name}'` } function safePropertyString(name: string) { return name.match(reSafePropertyName) ? name : `'${name}'` }
function doc(description: string, spacesCount: number) {
const spaces = ' '.repeat(spacesCount)
return [
`${spaces}/**`,
`${indentString(description, 1, `${spaces} * `)}`.replace(/ +\n/g, '\n'),
`${spaces} */`
].join('\n')
}
export function generate (name: string, info: string, schema: Database, fields?: Filter, importDatabasePath?: string) { export function generate (name: string, info: string, schema: Database, fields?: Filter, importDatabasePath?: string) {
const codeLines: string[] = [] const codeLines: string[] = []
codeLines.push(`export const ${name}_Schema = {`) codeLines.push(`export const ${name}_Schema = {`)
Object.keys(schema).forEach(table => { Object.keys(schema).forEach(table => {
if (fields && !fields[table]) return if (fields && !fields[table]) return
const { description, columns} = schema[table]
if (description) codeLines.push(doc(description, 4))
codeLines.push(` ${safePropertyString(table)}: {`) codeLines.push(` ${safePropertyString(table)}: {`)
const columns = schema[table]
Object.keys(columns).forEach(columnName => { Object.keys(columns).forEach(columnName => {
if (fields && !fields[table][columnName]) return if (fields && !fields[table][columnName]) return
const typeDef = getTypeDef(columns[columnName]) const c = columns[columnName]
if (columns[columnName].description) { const typeDef = getTypeDef(c)
codeLines.push(` /**`) if (c.description) codeLines.push(doc(c.description, 8))
codeLines.push(`${indentString(columns[columnName].description, 1, ' * ')}`)
codeLines.push(` */`)
}
codeLines.push(` ${safePropertyString(columnName)}: ${typeDef},`) codeLines.push(` ${safePropertyString(columnName)}: ${typeDef},`)
}) })
codeLines.push(' },') codeLines.push(' },')
}) })
codeLines.push('}') codeLines.push('}')
return `${header(name, info, importDatabasePath)}\n\n${codeLines.join('\n')}\n${footer(name)}` return `${header(name, info, importDatabasePath)}\n\n${getTypeShorthands(schema, fields)}\n\n${codeLines.join('\n')}\n${footer(name)}`
} }
...@@ -5,7 +5,11 @@ ...@@ -5,7 +5,11 @@
*/ */
export interface Database { [ tableName: string ]: Table } export interface Database { [ tableName: string ]: Table }
export interface Table { [ columnName: string ]: Column } export interface Table {
description: string
key: Set<string>
columns: { [ columnName: string ]: Column }
}
export type Column = IntCol | StrCol | FloatCol | CoordCol | EnumCol | VectorCol | MatrixCol | ListCol export type Column = IntCol | StrCol | FloatCol | CoordCol | EnumCol | VectorCol | MatrixCol | ListCol
type BaseCol = { description: string } type BaseCol = { description: string }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment