@aaswe/codebase-ai
Version:
AI-Assisted Software Engineering (AASWE) - Rich codebase context for IDE LLMs
517 lines • 20.6 kB
JavaScript
"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