package parser import ( "fmt" "io" "git.mchus.pro/mchus/logpile/internal/models" ) // BMCParser parses BMC diagnostic archives using vendor-specific parsers type BMCParser struct { result *models.AnalysisResult files []ExtractedFile vendorParser VendorParser } // NewBMCParser creates a new BMC parser func NewBMCParser() *BMCParser { return &BMCParser{ result: &models.AnalysisResult{ Events: make([]models.Event, 0), FRU: make([]models.FRUInfo, 0), Sensors: make([]models.SensorReading, 0), }, } } // ParseArchive parses an archive file func (p *BMCParser) ParseArchive(archivePath string) error { files, err := ExtractArchive(archivePath) if err != nil { return fmt.Errorf("extract archive: %w", err) } p.files = files return p.parseFiles() } // ParseFromReader parses archive from reader func (p *BMCParser) ParseFromReader(r io.Reader, filename string) error { files, err := ExtractArchiveFromReader(r, filename) if err != nil { return fmt.Errorf("extract archive: %w", err) } p.files = files p.result.Filename = filename return p.parseFiles() } func (p *BMCParser) parseFiles() error { // Auto-detect format vendorParser, err := DetectFormat(p.files) if err != nil { return fmt.Errorf("detect format: %w", err) } p.vendorParser = vendorParser // Parse using detected vendor parser result, err := vendorParser.Parse(p.files) if err != nil { return fmt.Errorf("parse with %s: %w", vendorParser.Name(), err) } // Preserve filename result.Filename = p.result.Filename p.result = result return nil } // Result returns the analysis result func (p *BMCParser) Result() *models.AnalysisResult { return p.result } // GetFiles returns all extracted files func (p *BMCParser) GetFiles() []ExtractedFile { return p.files } // DetectedVendor returns the detected vendor parser name func (p *BMCParser) DetectedVendor() string { if p.vendorParser != nil { return p.vendorParser.Name() } return "unknown" }