UNPKG

@aaswe/codebase-ai

Version:

AI-Assisted Software Engineering (AASWE) - Rich codebase context for IDE LLMs

517 lines 20.6 kB
"use strict"; /** * RDF Validator * * Production-quality validator for RDF/TTL files ensuring syntax correctness, * semantic consistency, and compliance with the AASWE ontology schema. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.RDFValidator = void 0; const n3_1 = require("n3"); const fs = __importStar(require("fs/promises")); const ontology_1 = require("./ontology"); const { namedNode } = n3_1.DataFactory; /** * Production-Quality RDF Validator * * Validates RDF content for syntax, semantics, and schema compliance * with comprehensive error reporting and suggestions. */ class RDFValidator { parser; store; errors = []; warnings = []; constructor() { this.parser = new n3_1.Parser({ format: 'text/turtle' }); this.store = new n3_1.Store(); } /** * Validate RDF Content */ async validateContent(rdfContent) { this.resetValidation(); try { // Parse RDF content await this.parseRDF(rdfContent); // Validate syntax and structure this.validateSyntax(); // Validate against ontology schema this.validateSchema(); // Validate semantic consistency this.validateSemantics(); // Check best practices this.checkBestPractices(); return { isValid: this.errors.length === 0, errors: [...this.errors], warnings: [...this.warnings], statistics: this.calculateStatistics() }; } catch (error) { this.addError('syntax', `Parse error: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error'); return { isValid: false, errors: [...this.errors], warnings: [...this.warnings], statistics: this.calculateStatistics() }; } } /** * Validate RDF File */ async validateFile(filePath) { try { const content = await fs.readFile(filePath, 'utf8'); return await this.validateContent(content); } catch (error) { this.addError('syntax', `File read error: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error'); return { isValid: false, errors: [...this.errors], warnings: [...this.warnings], statistics: this.calculateStatistics() }; } } /** * Parse RDF Content */ async parseRDF(rdfContent) { return new Promise((resolve, reject) => { const quads = []; this.parser.parse(rdfContent, (error, quad) => { if (error) { reject(error); return; } if (quad) { quads.push(quad); } else { // Parsing complete this.store.addQuads(quads); resolve(); } }); }); } /** * Validate Syntax */ validateSyntax() { const quads = this.store.getQuads(null, null, null, null); if (quads.length === 0) { this.addError('syntax', 'No RDF triples found in content', 'error'); return; } // Check for required namespaces this.validateNamespaces(); // Check URI validity this.validateURIs(); // Check literal types this.validateLiterals(); } /** * Validate Namespaces */ validateNamespaces() { const quads = this.store.getQuads(null, null, null, null); const usedNamespaces = new Set(); quads.forEach(quad => { if (quad.subject.termType === 'NamedNode') { const namespace = this.extractNamespace(quad.subject.value); if (namespace) usedNamespaces.add(namespace); } if (quad.predicate.termType === 'NamedNode') { const namespace = this.extractNamespace(quad.predicate.value); if (namespace) usedNamespaces.add(namespace); } if (quad.object.termType === 'NamedNode') { const namespace = this.extractNamespace(quad.object.value); if (namespace) usedNamespaces.add(namespace); } }); // Check for required AASWE namespaces const requiredNamespaces = Object.values(ontology_1.RDF_NAMESPACES); const missingNamespaces = requiredNamespaces.filter(ns => !usedNamespaces.has(ns)); if (missingNamespaces.length > 0) { this.addWarning('best_practice', `Missing recommended namespaces: ${missingNamespaces.join(', ')}`, 'Consider using AASWE ontology namespaces for better compatibility'); } } /** * Validate URIs */ validateURIs() { const quads = this.store.getQuads(null, null, null, null); quads.forEach(quad => { // Validate subject URIs if (quad.subject.termType === 'NamedNode') { this.validateURI(quad.subject.value, 'subject'); } // Validate predicate URIs if (quad.predicate.termType === 'NamedNode') { this.validateURI(quad.predicate.value, 'predicate'); } // Validate object URIs if (quad.object.termType === 'NamedNode') { this.validateURI(quad.object.value, 'object'); } }); } /** * Validate Single URI */ validateURI(uri, position) { try { new URL(uri); } catch { this.addError('syntax', `Invalid URI in ${position}: ${uri}`, 'error'); } // Check for common URI issues if (uri.includes(' ')) { this.addError('syntax', `Invalid URI in ${position}: ${uri}`, 'error'); } if (uri.length > 2000) { this.addWarning('performance', `Very long URI in ${position}: ${uri.substring(0, 50)}...`, 'Consider using shorter URIs for better performance'); } } /** * Validate Literals */ validateLiterals() { const quads = this.store.getQuads(null, null, null, null); quads.forEach(quad => { if (quad.object.termType === 'Literal') { this.validateLiteral(quad.object, quad.predicate.value); } }); } /** * Validate Single Literal */ validateLiteral(literal, predicate) { const value = literal.value; const datatype = literal.datatype?.value; // Check string length constraints if (datatype === 'http://www.w3.org/2001/XMLSchema#string' || !datatype) { if (value.length > ontology_1.VALIDATION_RULES.constraints.maxStringLength) { this.addWarning('performance', `Very long string literal: ${value.substring(0, 50)}...`, 'Consider breaking down large text into smaller chunks'); } } // Validate specific datatypes if (datatype) { this.validateDatatypeLiteral(value, datatype, predicate); } } /** * Validate Datatype Literals */ validateDatatypeLiteral(value, datatype, _predicate) { switch (datatype) { case 'http://www.w3.org/2001/XMLSchema#integer': if (!/^-?\d+$/.test(value)) { this.addError('semantic', `Invalid integer value: ${value}`, 'error'); } break; case 'http://www.w3.org/2001/XMLSchema#decimal': case 'http://www.w3.org/2001/XMLSchema#double': if (!/^-?\d*\.?\d+([eE][+-]?\d+)?$/.test(value)) { this.addError('semantic', `Invalid numeric value: ${value}`, 'error'); } break; case 'http://www.w3.org/2001/XMLSchema#boolean': if (!['true', 'false', '1', '0'].includes(value)) { this.addError('semantic', `Invalid boolean value: ${value}`, 'error'); } break; case 'http://www.w3.org/2001/XMLSchema#dateTime': if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) { this.addError('semantic', `Invalid dateTime value: ${value}`, 'error'); } break; } } /** * Validate Schema Compliance */ validateSchema() { this.validateRequiredProperties(); this.validatePropertyDomains(); this.validatePropertyRanges(); this.validateClassHierarchy(); } /** * Validate Required Properties */ validateRequiredProperties() { const classes = Object.keys(ontology_1.VALIDATION_RULES.required); classes.forEach(classUri => { const instances = this.store.getQuads(null, namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), namedNode(classUri), null); instances.forEach(instance => { const requiredProps = ontology_1.VALIDATION_RULES.required[classUri]; requiredProps.forEach(propUri => { const hasProperty = this.store.getQuads(instance.subject, namedNode(propUri), null, null); if (hasProperty.length === 0) { this.addError('schema', `Missing required property ${propUri} for instance ${instance.subject.value}`, 'error'); } }); }); }); } /** * Validate Property Domains */ validatePropertyDomains() { const propertyQuads = this.store.getQuads(null, null, null, null); propertyQuads.forEach(quad => { const predicate = quad.predicate.value; if (predicate === ontology_1.ONTOLOGY_PROPERTIES.hasMethod) { const subjectType = this.store.getQuads(quad.subject, namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), null, null); const isClass = subjectType.some(t => t.object.equals(namedNode(ontology_1.ONTOLOGY_CLASSES.Class))); if (!isClass) { this.addError('schema', `Property ${predicate} used with incorrect subject type`, 'error'); } } }); } /** * Validate Property Ranges */ validatePropertyRanges() { const propertyQuads = this.store.getQuads(null, null, null, null); propertyQuads.forEach(quad => { const predicate = quad.predicate.value; if (predicate === ontology_1.ONTOLOGY_PROPERTIES.extends && quad.object.termType === 'NamedNode') { const objectType = this.store.getQuads(quad.object, namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), null, null); const isClass = objectType.some(t => t.object.equals(namedNode(ontology_1.ONTOLOGY_CLASSES.Class))); if (!isClass) { this.addError('schema', `Property ${predicate} has incorrect object type`, 'error'); } } }); } /** * Validate Class Hierarchy */ validateClassHierarchy() { // Check for circular inheritance const inheritanceQuads = this.store.getQuads(null, namedNode(ontology_1.ONTOLOGY_PROPERTIES.extends), null, null); inheritanceQuads.forEach(quad => { if (this.hasCircularInheritance(quad.subject.value, quad.object.value)) { this.addError('semantic', `Circular inheritance detected: ${quad.subject.value} -> ${quad.object.value}`, 'error'); } }); } /** * Check for Circular Inheritance */ hasCircularInheritance(child, parent, visited = new Set()) { if (visited.has(child)) { return true; } if (child === parent) { return true; } visited.add(child); const parentQuads = this.store.getQuads(namedNode(parent), namedNode(ontology_1.ONTOLOGY_PROPERTIES.extends), null, null); for (const quad of parentQuads) { if (this.hasCircularInheritance(child, quad.object.value, new Set(visited))) { return true; } } return false; } /** * Validate Semantic Consistency */ validateSemantics() { this.validateUniqueIdentifiers(); this.validateReferentialIntegrity(); this.validateBusinessRules(); } /** * Validate Unique Identifiers */ validateUniqueIdentifiers() { const nameQuads = this.store.getQuads(null, namedNode(ontology_1.ONTOLOGY_PROPERTIES.fullyQualifiedName), null, null); const names = new Map(); nameQuads.forEach(quad => { const name = quad.object.value; if (!names.has(name)) { names.set(name, []); } names.get(name).push(quad.subject.value); }); names.forEach((subjects, name) => { if (subjects.length > 1) { this.addWarning('best_practice', `Duplicate fully qualified name: ${name} used by ${subjects.join(', ')}`, 'Consider using unique identifiers for better clarity'); } }); } /** * Validate Referential Integrity */ validateReferentialIntegrity() { // Check that all referenced entities exist const referenceProperties = [ ontology_1.ONTOLOGY_PROPERTIES.extends, ontology_1.ONTOLOGY_PROPERTIES.implements, ontology_1.ONTOLOGY_PROPERTIES.dependsOn ]; referenceProperties.forEach(prop => { const refs = this.store.getQuads(null, namedNode(prop), null, null); refs.forEach(ref => { if (ref.object.termType === 'NamedNode') { const exists = this.store.getQuads(ref.object, null, null, null); if (exists.length === 0) { this.addWarning('best_practice', `Reference to undefined entity: ${ref.object.value}`, 'Ensure all referenced entities are defined in the knowledge graph'); } } }); }); } /** * Validate Business Rules */ validateBusinessRules() { // Validate business rule consistency across the knowledge graph const businessRuleQuads = this.store.getQuads(null, namedNode(`${ontology_1.RDF_NAMESPACES.business}implementsRule`), null, null); businessRuleQuads.forEach(quad => { // Ensure business rules are properly defined and consistent const ruleExists = this.store.getQuads(quad.object, null, null, null); if (ruleExists.length === 0) { this.addWarning('business', `Business rule ${quad.object.value} is referenced but not defined`, 'Define the business rule or remove the reference'); } }); } /** * Check Best Practices */ checkBestPractices() { this.checkDocumentation(); this.checkNamingConventions(); this.checkComplexityMetrics(); } /** * Check Documentation Coverage */ checkDocumentation() { const classes = this.store.getQuads(null, namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), namedNode(ontology_1.ONTOLOGY_CLASSES.Class), null); classes.forEach(classQuad => { const hasDoc = this.store.getQuads(classQuad.subject, namedNode(ontology_1.ONTOLOGY_PROPERTIES.summary), null, null); if (hasDoc.length === 0) { this.addWarning('best_practice', `Class ${classQuad.subject.value} lacks documentation`, 'Add summary and description for better LLM understanding'); } }); } /** * Check Naming Conventions */ checkNamingConventions() { const nameQuads = this.store.getQuads(null, namedNode(ontology_1.ONTOLOGY_PROPERTIES.name), null, null); nameQuads.forEach(quad => { const name = quad.object.value; // Check naming patterns if (!/^[A-Z][a-zA-Z0-9]*$/.test(name)) { this.addWarning('best_practice', `Non-standard naming convention: ${name}`, 'Consider using PascalCase for class names'); } }); } /** * Check Complexity Metrics */ checkComplexityMetrics() { const complexityQuads = this.store.getQuads(null, namedNode(ontology_1.ONTOLOGY_PROPERTIES.cyclomaticComplexity), null, null); complexityQuads.forEach(quad => { const complexity = parseInt(quad.object.value); if (complexity > 10) { this.addWarning('best_practice', `High cyclomatic complexity: ${complexity} for ${quad.subject.value}`, 'Consider refactoring to reduce complexity'); } }); } /** * Helper Methods */ resetValidation() { this.errors = []; this.warnings = []; this.store.removeQuads(this.store.getQuads(null, null, null, null)); } addError(type, message, severity, line, column) { this.errors.push({ type: type, message, ...(line !== undefined && { line }), ...(column !== undefined && { column }), severity }); } addWarning(type, message, suggestion) { this.warnings.push({ type: type, message, suggestion }); } extractNamespace(uri) { const match = uri.match(/^(https?:\/\/[^\/]+\/[^#]*[#\/])/); return match ? match[1] : null; } calculateStatistics() { const quads = this.store.getQuads(null, null, null, null); return { totalTriples: quads.length, classCount: this.store.getQuads(null, namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), namedNode(ontology_1.ONTOLOGY_CLASSES.Class), null).length, methodCount: this.store.getQuads(null, namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), namedNode(ontology_1.ONTOLOGY_CLASSES.Method), null).length, propertyCount: this.store.getQuads(null, namedNode(ontology_1.ONTOLOGY_PROPERTIES.hasProperty), null, null).length, dependencyCount: this.store.getQuads(null, namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), namedNode(ontology_1.ONTOLOGY_CLASSES.Dependency), null).length, documentationTriples: this.store.getQuads(null, namedNode(ontology_1.ONTOLOGY_PROPERTIES.summary), null, null).length + this.store.getQuads(null, namedNode(ontology_1.ONTOLOGY_PROPERTIES.description), null, null).length, businessContextTriples: quads.filter(q => q.predicate.value.includes(ontology_1.RDF_NAMESPACES.business)).length, qualityMetricTriples: quads.filter(q => q.predicate.value.includes(ontology_1.RDF_NAMESPACES.quality)).length }; } } exports.RDFValidator = RDFValidator; //# sourceMappingURL=RDFValidator.js.map