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
No related branches found
No related tags found
No related merge requests found
......@@ -77,7 +77,7 @@ interface FrameData {
}
// get field from given or linked category
function getField ( category: string, field: string, d: Data.CifFrame, ctx: FrameData): Data.CifField|undefined {
function getField (category: string, field: string, d: Data.CifFrame, ctx: FrameData): Data.CifField|undefined {
const { categories, links } = ctx
const cat = d.categories[category]
......@@ -130,6 +130,7 @@ function getSubCategory (d: Data.CifFrame, ctx: FrameData): string|undefined {
function getDescription (d: Data.CifFrame, ctx: FrameData): string|undefined {
const value = getField('item_description', 'description', d, ctx)
if (value) {
// trim (after newlines) and remove references to square brackets
return value.str(0).trim()
.replace(/(\r\n|\r|\n)([ \t]+)/g, '\n')
.replace(/(\[[1-3]\])+ element/, 'elements')
......@@ -195,6 +196,40 @@ export function generateSchema (frames: CifFrame[]) {
const links: FrameLinks = {}
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
frames.forEach(d => {
if (d.header[0] !== '_') return
......@@ -216,6 +251,7 @@ export function generateSchema (frames: CifFrame[]) {
}
})
// get field data
Object.keys(categories).forEach(fullName => {
const d = categories[fullName]
if (!d) {
......@@ -226,10 +262,15 @@ export function generateSchema (frames: CifFrame[]) {
const itemName = d.header.substring(d.header.indexOf('.') + 1)
let fields: { [k: string]: Column }
if (categoryName in schema) {
fields = schema[categoryName]
fields = schema[categoryName].columns
} else {
console.log(`category '${categoryName}' has no metadata`)
fields = {}
schema[categoryName] = fields
schema[categoryName] = {
description: '',
key: new Set(),
columns: fields
}
}
const description = getDescription(d, ctx) || ''
......
......@@ -18,17 +18,7 @@ function header (name: string, info: string, importDatabasePath = 'mol-data/db')
import { Database, Column } from '${importDatabasePath}'
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;`
import Schema = Column.Schema`
}
function footer (name: string) {
......@@ -37,6 +27,32 @@ export type ${name}_Schema = typeof ${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 {
switch (c.type) {
case 'str': return 'str'
......@@ -63,27 +79,34 @@ function getTypeDef(c: Column): string {
const reSafePropertyName = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/
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) {
const codeLines: string[] = []
codeLines.push(`export const ${name}_Schema = {`)
Object.keys(schema).forEach(table => {
if (fields && !fields[table]) return
const { description, columns} = schema[table]
if (description) codeLines.push(doc(description, 4))
codeLines.push(` ${safePropertyString(table)}: {`)
const columns = schema[table]
Object.keys(columns).forEach(columnName => {
if (fields && !fields[table][columnName]) return
const typeDef = getTypeDef(columns[columnName])
if (columns[columnName].description) {
codeLines.push(` /**`)
codeLines.push(`${indentString(columns[columnName].description, 1, ' * ')}`)
codeLines.push(` */`)
}
const c = columns[columnName]
const typeDef = getTypeDef(c)
if (c.description) codeLines.push(doc(c.description, 8))
codeLines.push(` ${safePropertyString(columnName)}: ${typeDef},`)
})
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 @@
*/
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
type BaseCol = { description: string }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment