in doc-architect/doc-architect-core/src/main/java/com/docarchitect/core/scanner/impl/python/DjangoOrmScanner.java [202:259]
public ScanResult scan(ScanContext context) {
log.info("Scanning Django models in: {}", context.rootPath());
List<DataEntity> dataEntities = new ArrayList<>();
List<Relationship> relationships = new ArrayList<>();
ScanStatistics.Builder statsBuilder = new ScanStatistics.Builder();
List<Path> modelFiles = new ArrayList<>();
context.findFiles(PATTERN_MODELS_PY).forEach(modelFiles::add);
context.findFiles(PATTERN_MODELS_SUFFIX).forEach(modelFiles::add);
statsBuilder.filesDiscovered(modelFiles.size());
if (modelFiles.isEmpty()) {
return emptyResult();
}
int skippedFiles = 0;
for (Path modelFile : modelFiles) {
if (!shouldScanFile(modelFile)) {
skippedFiles++;
continue;
}
statsBuilder.incrementFilesScanned();
// Use three-tier parsing with fallback
FileParseResult<EntityResult> result = parseWithFallback(
modelFile,
classes -> extractEntitiesFromAST(classes),
createFallbackStrategy(),
statsBuilder
);
if (result.isSuccess()) {
for (EntityResult entityResult : result.getData()) {
dataEntities.add(entityResult.entity());
relationships.addAll(entityResult.relationships());
}
}
}
ScanStatistics statistics = statsBuilder.build();
log.info("Found {} Django models and {} relationships (success rate: {:.1f}%, overall parse rate: {:.1f}%, skipped {} files)",
dataEntities.size(), relationships.size(), statistics.getSuccessRate(), statistics.getOverallParseRate(), skippedFiles);
return buildSuccessResult(
List.of(), // No components
List.of(), // No dependencies
List.of(), // No API endpoints
List.of(), // No message flows
dataEntities, // Data entities
relationships, // Relationships
List.of(), // No warnings
statistics
);
}