package main import ( "fmt" "os" "path/filepath" "strings" "time" ) // Hl7FhirHandlerData contains template data for HL7 FHIR handler generation type Hl7FhirHandlerData struct { Name string NameLower string NameUpper string Category string CategoryPath string CategoryParts []string ModuleName string HasGet bool HasPost bool HasPut bool HasPatch bool HasDelete bool HasSearch bool HasHistory bool GetEndpoint string PostEndpoint string PutEndpoint string PatchEndpoint string DeleteEndpoint string SearchEndpoint string HistoryEndpoint string Timestamp string DirectoryDepth int FhirResource string FhirVersion string // R4, R5 Profile string // US Core, AU Base, UK Core, etc. } func main() { if len(os.Args) < 2 { fmt.Println("Usage: go run generate-hl7fhir-handler.go [level1[/level2[/level3[/level4]]]]/entity [methods] [--version=R4|R5] [--profile=profile]") fmt.Println("Examples:") fmt.Println(" go run generate-hl7fhir-handler.go fhir/patient get post put patch --version=R4") fmt.Println(" go run generate-hl7fhir-handler.go us-core/patient get post search --profile=USCore") fmt.Println(" go run generate-hl7fhir-handler.go au-base/practitioner get post --profile=AUBase --version=R4") fmt.Println(" go run generate-hl7fhir-handler.go api/v1/fhir/r4/observation get post put patch delete search history") fmt.Println(" go run generate-hl7fhir-handler.go medication get") os.Exit(1) } // Parse entity path (up to 4 levels + entity) entityPath := os.Args[1] methods := []string{} fhirVersion := "R4" // Default to R4 profile := "" // Default to no specific profile // Parse arguments for i := 2; i < len(os.Args); i++ { arg := os.Args[i] if strings.HasPrefix(arg, "--version=") { fhirVersion = strings.TrimPrefix(arg, "--version=") } else if strings.HasPrefix(arg, "--profile=") { profile = strings.TrimPrefix(arg, "--profile=") } else { methods = append(methods, arg) } } if len(methods) == 0 { // Default methods for FHIR resources methods = []string{"get", "post", "put", "patch", "search"} } // Parse multi-level category and entity var categoryParts []string var entityName string var category string parts := strings.Split(entityPath, "/") if len(parts) > 1 && len(parts) <= 5 { // Up to 4 levels + entity categoryParts = parts[:len(parts)-1] entityName = parts[len(parts)-1] category = strings.Join(categoryParts, "/") } else if len(parts) == 1 { category = "" entityName = parts[0] categoryParts = []string{} } else { fmt.Println("❌ Error: Invalid path format. Use up to 4 levels like 'level1/level2/level3/level4/entity' or just 'entity'") fmt.Printf("❌ You provided %d levels, maximum is 4 levels + entity\n", len(parts)-1) os.Exit(1) } // Format names entityName = strings.Title(entityName) // PascalCase entity name entityLower := strings.ToLower(entityName) entityUpper := strings.ToUpper(entityName) // FHIR Resource name (capitalize first letter only) fhirResource := strings.Title(strings.ToLower(entityName)) data := Hl7FhirHandlerData{ Name: entityName, NameLower: entityLower, NameUpper: entityUpper, Category: category, CategoryPath: category, CategoryParts: categoryParts, ModuleName: "api-service", DirectoryDepth: len(categoryParts), FhirResource: fhirResource, FhirVersion: fhirVersion, Profile: profile, Timestamp: time.Now().Format("2006-01-02 15:04:05"), } // Set methods and endpoints for FHIR resources for _, m := range methods { switch strings.ToLower(m) { case "get": data.HasGet = true data.GetEndpoint = fmt.Sprintf("%s/{id}", fhirResource) case "post": data.HasPost = true data.PostEndpoint = fhirResource case "put": data.HasPut = true data.PutEndpoint = fmt.Sprintf("%s/{id}", fhirResource) case "patch": data.HasPatch = true data.PatchEndpoint = fmt.Sprintf("%s/{id}", fhirResource) case "delete": data.HasDelete = true data.DeleteEndpoint = fmt.Sprintf("%s/{id}", fhirResource) case "search": data.HasSearch = true data.SearchEndpoint = fhirResource case "history": data.HasHistory = true data.HistoryEndpoint = fmt.Sprintf("%s/{id}/_history", fhirResource) } } // Create directories with multi-level support var handlerDir, modelDir string if category != "" { // Multi-level directory support handlerDirParts := append([]string{"internal", "handlers", "hl7fhir"}, categoryParts...) modelDirParts := append([]string{"internal", "models", "hl7fhir"}, categoryParts...) handlerDir = filepath.Join(handlerDirParts...) modelDir = filepath.Join(modelDirParts...) } else { // No category: direct internal/handlers/hl7fhir/ handlerDir = filepath.Join("internal", "handlers", "hl7fhir") modelDir = filepath.Join("internal", "models", "hl7fhir") } // Create directories for _, d := range []string{handlerDir, modelDir} { if err := os.MkdirAll(d, 0755); err != nil { panic(err) } } // Generate files generateOptimizedHl7FhirHandlerFile(data, handlerDir) generateOptimizedHl7FhirModelFile(data, modelDir) // updateOptimizedHl7FhirRoutesFile(data) fmt.Printf("✅ Successfully generated optimized HL7 FHIR handler: %s\n", entityName) if category != "" { fmt.Printf("📁 Category Path: %s (%d levels deep)\n", category, data.DirectoryDepth) } fmt.Printf("📁 FHIR Resource: %s\n", fhirResource) fmt.Printf("📁 FHIR Version: %s\n", fhirVersion) if profile != "" { fmt.Printf("📁 FHIR Profile: %s\n", profile) } fmt.Printf("📁 Handler: %s\n", filepath.Join(handlerDir, entityLower+".go")) fmt.Printf("📁 Model: %s\n", filepath.Join(modelDir, entityLower+".go")) } // ================= OPTIMIZED HANDLER GENERATION ===================== func generateOptimizedHl7FhirHandlerFile(data Hl7FhirHandlerData, handlerDir string) { var modelsImportPath string if data.Category != "" { modelsImportPath = data.ModuleName + "/internal/models/hl7fhir/" + data.Category } else { modelsImportPath = data.ModuleName + "/internal/models/hl7fhir" } profileInfo := "" if data.Profile != "" { profileInfo = fmt.Sprintf("// FHIR Profile: %s\n", data.Profile) } handlerContent := `package handlers import ( "context" "fmt" "net/http" "strconv" "time" "` + data.ModuleName + `/internal/config" "` + modelsImportPath + `" services "` + data.ModuleName + `/internal/services/hl7fhir" "` + data.ModuleName + `/pkg/logger" "` + data.ModuleName + `/pkg/validator" "api-service/pkg/utils" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/go-playground/validator/v10" ) // ` + data.Name + `Handler handles ` + data.NameLower + ` HL7 FHIR services with multi-level organization // Generated for FHIR Resource: ` + data.FhirResource + ` // FHIR Version: ` + data.FhirVersion + ` ` + profileInfo + `// Path: ` + data.Category + ` // Directory depth: ` + fmt.Sprintf("%d", data.DirectoryDepth) + ` levels type ` + data.Name + `Handler struct { service services.Hl7FhirService validator *validator.Validate logger logger.Logger config *config.Hl7FhirConfig } // HandlerConfig contains configuration for ` + data.Name + `Handler type ` + data.Name + `HandlerConfig struct { Hl7FhirConfig *config.Hl7FhirConfig Logger logger.Logger Validator *validator.Validate } // New` + data.Name + `Handler creates a new optimized ` + data.Name + `Handler for HL7 FHIR func New` + data.Name + `Handler(cfg *` + data.Name + `HandlerConfig) *` + data.Name + `Handler { return &` + data.Name + `Handler{ service: services.NewHl7FhirService(cfg.Hl7FhirConfig), validator: cfg.Validator, logger: cfg.Logger, config: cfg.Hl7FhirConfig, } }` // Add optimized methods based on flags if data.HasPost { handlerContent += generateOptimizedHl7FhirCreateMethod(data) } if data.HasPut { handlerContent += generateOptimizedHl7FhirUpdateMethod(data) } if data.HasPatch { handlerContent += generateOptimizedHl7FhirPatchMethod(data) } if data.HasDelete { handlerContent += generateOptimizedHl7FhirDeleteMethod(data) } if data.HasGet { handlerContent += generateOptimizedHl7FhirGetMethod(data) } if data.HasSearch { handlerContent += generateOptimizedHl7FhirSearchMethod(data) } if data.HasHistory { handlerContent += generateOptimizedHl7FhirHistoryMethod(data) } // Add helper methods handlerContent += generateHl7FhirHelperMethods(data) writeFile(filepath.Join(handlerDir, data.NameLower+".go"), handlerContent) } func generateOptimizedHl7FhirCreateMethod(data Hl7FhirHandlerData) string { var routePath, tagName string if data.Category != "" { routePath = "hl7fhir/" + data.Category + "/" + data.NameLower tagParts := append([]string{"HL7FHIR"}, data.CategoryParts...) tagParts = append(tagParts, strings.Title(data.NameLower)) tagName = strings.Join(tagParts, "-") } else { routePath = "hl7fhir/" + data.NameLower tagName = "HL7FHIR-" + strings.Title(data.NameLower) } profileTag := "" if data.Profile != "" { profileTag = fmt.Sprintf(" (%s Profile)", data.Profile) } return ` // Create` + data.Name + ` creates a new HL7 FHIR ` + data.FhirResource + ` resource // @Summary Create a new HL7 FHIR ` + data.FhirResource + ` resource // @Description Create a new ` + data.FhirResource + ` resource compliant with HL7 FHIR ` + data.FhirVersion + `` + profileTag + ` // @Description FHIR Resource: ` + data.FhirResource + ` | Version: ` + data.FhirVersion + ` | Path: ` + data.Category + ` // @Tags ` + tagName + ` // @Accept json // @Produce json // @Param Accept header string false "Preferred response format (application/fhir+json, application/json)" // @Param Content-Type header string true "Request content type (application/fhir+json, application/json)" // @Param Prefer header string false "Return preference (return=minimal, return=representation, return=OperationOutcome)" // @Param request body models.` + data.Name + `CreateRequest true "` + data.FhirResource + ` FHIR resource creation request" // @Success 201 {object} models.` + data.Name + `Response "` + data.FhirResource + ` resource created successfully" // @Failure 400 {object} models.Hl7FhirOperationOutcome "Bad request - validation error" // @Failure 422 {object} models.Hl7FhirOperationOutcome "Unprocessable entity - FHIR validation error" // @Failure 500 {object} models.Hl7FhirOperationOutcome "Internal server error" // @Router /api/v1/` + routePath + ` [post] func (h *` + data.Name + `Handler) Create` + data.Name + `(c *gin.Context) { requestID := uuid.New().String() startTime := time.Now() h.logger.Info("Creating HL7 FHIR ` + data.FhirResource + ` resource", map[string]interface{}{ "request_id": requestID, "timestamp": startTime, "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "fhir_profile": "` + data.Profile + `", "category_path": "` + data.Category + `", "directory_depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `, "content_type": c.GetHeader("Content-Type"), "accept": c.GetHeader("Accept"), "prefer": c.GetHeader("Prefer"), }) var req models.` + data.Name + `CreateRequest req.RequestID = requestID req.Timestamp = startTime // Enhanced JSON binding with HL7 FHIR validation if err := c.ShouldBindJSON(&req); err != nil { h.logger.Error("Failed to bind HL7 FHIR JSON", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "path": "` + routePath + `", }) h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "structure", "Invalid FHIR resource structure", err.Error(), requestID) return } // HL7 FHIR resource validation if err := req.ValidateHl7Fhir(); err != nil { h.logger.Error("HL7 FHIR validation failed", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "path": "` + routePath + `", }) h.sendHl7FhirErrorResponse(c, http.StatusUnprocessableEntity, "business-rule", "HL7 FHIR resource validation failed", err.Error(), requestID) return } // Profile-specific validation if "` + data.Profile + `" != "" { if err := req.ValidateProfile("` + data.Profile + `"); err != nil { h.logger.Error("Profile validation failed", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "fhir_resource": "` + data.FhirResource + `", "fhir_profile": "` + data.Profile + `", "path": "` + routePath + `", }) h.sendHl7FhirErrorResponse(c, http.StatusUnprocessableEntity, "business-rule", "Profile validation failed", err.Error(), requestID) return } } // Struct validation if err := h.validator.Struct(&req); err != nil { h.logger.Error("Struct validation failed", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "fhir_resource": "` + data.FhirResource + `", "path": "` + routePath + `", }) h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "structure", "Resource structure validation failed", h.formatValidationError(err), requestID) return } ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() var fhirResponse models.Hl7FhirResponse if err := h.service.CreateResource(ctx, "` + data.PostEndpoint + `", req, &fhirResponse); err != nil { h.logger.Error("Failed to create HL7 FHIR resource", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "endpoint": "` + data.PostEndpoint + `", "path": "` + routePath + `", }) statusCode, errorCode := h.categorizeHl7FhirError(err) h.sendHl7FhirErrorResponse(c, statusCode, errorCode, "Failed to create ` + data.FhirResource + ` resource", err.Error(), requestID) return } // Check for HL7 FHIR OperationOutcome if fhirResponse.ResourceType == "OperationOutcome" { h.logger.Warn("HL7 FHIR server returned OperationOutcome", map[string]interface{}{ "request_id": requestID, "fhir_resource": "` + data.FhirResource + `", "path": "` + routePath + `", "outcome": fhirResponse, }) h.sendHl7FhirOperationOutcome(c, http.StatusUnprocessableEntity, fhirResponse, requestID) return } duration := time.Since(startTime) h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource created successfully", map[string]interface{}{ "request_id": requestID, "duration": duration.String(), "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "resource_id": fhirResponse.ID, "path": "` + routePath + `", }) // Handle Prefer header for response prefer := c.GetHeader("Prefer") if strings.Contains(prefer, "return=minimal") { c.Header("Location", fmt.Sprintf("%s/%s", "` + data.FhirResource + `", fhirResponse.ID)) c.Header("ETag", fmt.Sprintf("W/\"%s\"", fhirResponse.Meta.VersionId)) c.Header("Last-Modified", fhirResponse.Meta.LastUpdated) c.Status(http.StatusCreated) return } h.sendHl7FhirSuccessResponse(c, http.StatusCreated, "` + data.FhirResource + ` resource created successfully", fhirResponse, requestID) }` } func generateOptimizedHl7FhirSearchMethod(data Hl7FhirHandlerData) string { var routePath, tagName string if data.Category != "" { routePath = "hl7fhir/" + data.Category + "/" + data.NameLower tagParts := append([]string{"HL7FHIR"}, data.CategoryParts...) tagParts = append(tagParts, strings.Title(data.NameLower)) tagName = strings.Join(tagParts, "-") } else { routePath = "hl7fhir/" + data.NameLower tagName = "HL7FHIR-" + strings.Title(data.NameLower) } profileTag := "" if data.Profile != "" { profileTag = fmt.Sprintf(" (%s Profile)", data.Profile) } return ` // Search` + data.Name + ` searches for HL7 FHIR ` + data.FhirResource + ` resources with parameters // @Summary Search for HL7 FHIR ` + data.FhirResource + ` resources // @Description Search for ` + data.FhirResource + ` resources compliant with HL7 FHIR ` + data.FhirVersion + `` + profileTag + ` using search parameters // @Description FHIR Resource: ` + data.FhirResource + ` | Version: ` + data.FhirVersion + ` | Path: ` + data.Category + ` // @Tags ` + tagName + ` // @Accept json // @Produce json // @Param Accept header string false "Preferred response format (application/fhir+json, application/json)" // @Param _count query integer false "Number of results to return (default: 10, max: 50)" // @Param _page query integer false "Page number for pagination (default: 1)" // @Param _include query string false "Include referenced resources" // @Param _revinclude query string false "Reverse include referenced resources" // @Param _sort query string false "Sort parameters (field1,-field2)" // @Param _elements query string false "Elements to return (comma-separated)" // @Param _summary query string false "Summary mode (true, text, data, count, false)" // @Param _format query string false "Response format override (json, xml)" // @Success 200 {object} models.Hl7FhirBundleResponse "` + data.FhirResource + ` resources search results" // @Failure 400 {object} models.Hl7FhirOperationOutcome "Bad request - invalid search parameters" // @Failure 500 {object} models.Hl7FhirOperationOutcome "Internal server error" // @Router /api/v1/` + routePath + ` [get] func (h *` + data.Name + `Handler) Search` + data.Name + `(c *gin.Context) { requestID := uuid.New().String() startTime := time.Now() h.logger.Info("Searching HL7 FHIR ` + data.FhirResource + ` resources", map[string]interface{}{ "request_id": requestID, "timestamp": startTime, "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "fhir_profile": "` + data.Profile + `", "query_params": c.Request.URL.Query(), "category_path": "` + data.Category + `", "directory_depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `, "accept": c.GetHeader("Accept"), }) ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second) defer cancel() // Parse and validate search parameters searchParams := make(map[string]string) for key, values := range c.Request.URL.Query() { if len(values) > 0 { searchParams[key] = values[0] } } // Validate pagination parameters count := 10 // default if countStr := searchParams["_count"]; countStr != "" { if parsedCount, err := strconv.Atoi(countStr); err == nil { if parsedCount > 0 && parsedCount <= 50 { count = parsedCount } } } page := 1 // default if pageStr := searchParams["_page"]; pageStr != "" { if parsedPage, err := strconv.Atoi(pageStr); err == nil && parsedPage > 0 { page = parsedPage } } // Add pagination info to search params searchParams["_count"] = fmt.Sprintf("%d", count) searchParams["_page"] = fmt.Sprintf("%d", page) var fhirBundle models.Hl7FhirBundleResponse if err := h.service.SearchResources(ctx, "` + data.FhirResource + `", searchParams, &fhirBundle); err != nil { h.logger.Error("Failed to search HL7 FHIR resources", map[string]interface{}{ "error": err.Error(), "request_id": requestID, "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "search_params": searchParams, "path": "` + routePath + `", }) statusCode, errorCode := h.categorizeHl7FhirError(err) h.sendHl7FhirErrorResponse(c, statusCode, errorCode, "Failed to search ` + data.FhirResource + ` resources", err.Error(), requestID) return } duration := time.Since(startTime) h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resources search completed", map[string]interface{}{ "request_id": requestID, "duration": duration.String(), "fhir_resource": "` + data.FhirResource + `", "fhir_version": "` + data.FhirVersion + `", "total_results": fhirBundle.Total, "search_params": searchParams, "path": "` + routePath + `", }) h.sendHl7FhirBundleResponse(c, http.StatusOK, "` + data.FhirResource + ` resources search completed", fhirBundle, requestID) }` } func generateHl7FhirHelperMethods(data Hl7FhirHandlerData) string { return ` // Helper methods for ` + data.Name + `Handler with HL7 FHIR support func (h *` + data.Name + `Handler) sendHl7FhirSuccessResponse(c *gin.Context, statusCode int, message string, data interface{}, requestID string) { response := models.` + data.Name + `Response{ Hl7FhirResource: models.Hl7FhirResource{ ResourceType: "` + data.FhirResource + `", Meta: models.Hl7FhirMeta{ LastUpdated: time.Now().Format(time.RFC3339), VersionId: "1", FhirVersion: "` + data.FhirVersion + `", Profile: h.getProfileUrl("` + data.Profile + `"), }, }, BaseResponse: models.BaseResponse{ Status: "success", Message: message, Data: data, Metadata: &models.ResponseMetadata{ Timestamp: time.Now(), Version: "HL7 FHIR ` + data.FhirVersion + `", RequestID: requestID, Path: "` + data.Category + `", Depth: ` + fmt.Sprintf("%d", data.DirectoryDepth) + `, FhirResource: "` + data.FhirResource + `", FhirVersion: "` + data.FhirVersion + `", FhirProfile: "` + data.Profile + `", }, }, } // Set appropriate FHIR headers c.Header("Content-Type", "application/fhir+json; fhirVersion=` + data.FhirVersion + `") c.Header("ETag", fmt.Sprintf("W/\"%s\"", response.Hl7FhirResource.Meta.VersionId)) c.Header("Last-Modified", response.Hl7FhirResource.Meta.LastUpdated) c.JSON(statusCode, response) } func (h *` + data.Name + `Handler) sendHl7FhirErrorResponse(c *gin.Context, statusCode int, errorCode, message, details, requestID string) { operationOutcome := models.Hl7FhirOperationOutcome{ ResourceType: "OperationOutcome", ID: requestID, Meta: models.Hl7FhirMeta{ LastUpdated: time.Now().Format(time.RFC3339), VersionId: "1", FhirVersion: "` + data.FhirVersion + `", }, Issue: []models.Hl7FhirOperationOutcomeIssue{{ Severity: h.mapHttpStatusToSeverity(statusCode), Code: errorCode, Details: models.Hl7FhirCodeableConcept{ Text: message, Coding: []models.Hl7FhirCoding{{ System: "http://terminology.hl7.org/CodeSystem/operation-outcome", Code: errorCode, Display: message, }}, }, Diagnostics: details, Location: []string{fmt.Sprintf("` + data.FhirResource + `")}, Expression: []string{fmt.Sprintf("` + data.FhirResource + `")}, }}, } c.Header("Content-Type", "application/fhir+json; fhirVersion=` + data.FhirVersion + `") c.JSON(statusCode, operationOutcome) } func (h *` + data.Name + `Handler) sendHl7FhirOperationOutcome(c *gin.Context, statusCode int, outcome models.Hl7FhirResponse, requestID string) { c.Header("Content-Type", "application/fhir+json; fhirVersion=` + data.FhirVersion + `") c.JSON(statusCode, outcome) } func (h *` + data.Name + `Handler) sendHl7FhirBundleResponse(c *gin.Context, statusCode int, message string, bundle models.Hl7FhirBundleResponse, requestID string) { bundle.Meta = models.Hl7FhirMeta{ LastUpdated: time.Now().Format(time.RFC3339), VersionId: "1", FhirVersion: "` + data.FhirVersion + `", } // Add self link bundle.Link = append(bundle.Link, models.Hl7FhirBundleLink{ Relation: "self", URL: fmt.Sprintf("%s?%s", "` + data.FhirResource + `", h.buildQueryString(bundle.SearchParams)), }) c.Header("Content-Type", "application/fhir+json; fhirVersion=` + data.FhirVersion + `") c.JSON(statusCode, bundle) } func (h *` + data.Name + `Handler) formatValidationError(err error) string { if validationErrors, ok := err.(validator.ValidationErrors); ok { var messages []string for _, e := range validationErrors { switch e.Tag() { case "required": messages = append(messages, fmt.Sprintf("Field '%s' is required", e.Field())) case "min": messages = append(messages, fmt.Sprintf("Field '%s' must be at least %s characters", e.Field(), e.Param())) case "max": messages = append(messages, fmt.Sprintf("Field '%s' must be at most %s characters", e.Field(), e.Param())) case "oneof": messages = append(messages, fmt.Sprintf("Field '%s' must be one of: %s", e.Field(), e.Param())) case "url": messages = append(messages, fmt.Sprintf("Field '%s' must be a valid URL", e.Field())) case "uuid": messages = append(messages, fmt.Sprintf("Field '%s' must be a valid UUID", e.Field())) case "datetime": messages = append(messages, fmt.Sprintf("Field '%s' must be a valid datetime", e.Field())) default: messages = append(messages, fmt.Sprintf("Field '%s' is invalid", e.Field())) } } return fmt.Sprintf("HL7 FHIR validation failed: %v", messages) } return err.Error() } func (h *` + data.Name + `Handler) categorizeHl7FhirError(err error) (int, string) { if err == nil { return http.StatusOK, "informational" } errStr := err.Error() // HL7 FHIR-specific error categorization if strings.Contains(errStr, "unauthorized") || strings.Contains(errStr, "invalid token") { return http.StatusUnauthorized, "security" } if strings.Contains(errStr, "not found") || strings.Contains(errStr, "404") { return http.StatusNotFound, "not-found" } if strings.Contains(errStr, "validation") || strings.Contains(errStr, "invalid") { return http.StatusUnprocessableEntity, "business-rule" } if strings.Contains(errStr, "duplicate") || strings.Contains(errStr, "conflict") { return http.StatusConflict, "duplicate" } if h.isTimeoutError(err) { return http.StatusRequestTimeout, "timeout" } if h.isNetworkError(err) { return http.StatusBadGateway, "transient" } return http.StatusInternalServerError, "exception" } func (h *` + data.Name + `Handler) mapHttpStatusToSeverity(statusCode int) string { switch { case statusCode >= 500: return "fatal" case statusCode >= 400: return "error" case statusCode >= 300: return "warning" default: return "information" } } func (h *` + data.Name + `Handler) getProfileUrl(profile string) []string { profileUrls := map[string]string{ "USCore": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-` + strings.ToLower(data.FhirResource) + `", "AUBase": "http://hl7.org.au/fhir/base/StructureDefinition/au-` + strings.ToLower(data.FhirResource) + `", "UKCore": "https://fhir.hl7.org.uk/StructureDefinition/UKCore-` + data.FhirResource + `", "CABaseline": "http://hl7.org/fhir/ca/baseline/StructureDefinition/profile-` + strings.ToLower(data.FhirResource) + `", "InternationalPatientSummary": "http://hl7.org/fhir/uv/ips/StructureDefinition/` + data.FhirResource + `-uv-ips", } if profile != "" { if url, exists := profileUrls[profile]; exists { return []string{url} } } return []string{} } func (h *` + data.Name + `Handler) buildQueryString(params map[string]string) string { var parts []string for key, value := range params { parts = append(parts, fmt.Sprintf("%s=%s", key, value)) } return strings.Join(parts, "&") } func (h *` + data.Name + `Handler) isTimeoutError(err error) bool { return err != nil && (strings.Contains(err.Error(), "timeout") || strings.Contains(err.Error(), "deadline exceeded")) } func (h *` + data.Name + `Handler) isNetworkError(err error) bool { return err != nil && (strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "no such host") || strings.Contains(err.Error(), "network unreachable")) }` } func generateOptimizedHl7FhirModelFile(data Hl7FhirHandlerData, modelDir string) { profileInfo := "" if data.Profile != "" { profileInfo = fmt.Sprintf("// FHIR Profile: %s\n", data.Profile) } modelContent := `package models import ( "encoding/json" "fmt" "strings" "time" "regexp" ) // ` + data.Name + ` HL7 FHIR ` + data.FhirVersion + ` Models with Enhanced Multi-Level Support // Generated at: ` + data.Timestamp + ` // FHIR Resource: ` + data.FhirResource + ` // FHIR Version: ` + data.FhirVersion + ` ` + profileInfo + `// Category Path: ` + data.Category + ` // Directory Depth: ` + fmt.Sprintf("%d", data.DirectoryDepth) + ` levels // Base HL7 FHIR structures type Hl7FhirResource struct { ResourceType string ` + "`json:\"resourceType\"`" + ` ID string ` + "`json:\"id,omitempty\"`" + ` Meta Hl7FhirMeta ` + "`json:\"meta,omitempty\"`" + ` ImplicitRules string ` + "`json:\"implicitRules,omitempty\"`" + ` Language string ` + "`json:\"language,omitempty\"`" + ` } type Hl7FhirMeta struct { VersionId string ` + "`json:\"versionId,omitempty\"`" + ` LastUpdated string ` + "`json:\"lastUpdated,omitempty\"`" + ` Source string ` + "`json:\"source,omitempty\"`" + ` Profile []string ` + "`json:\"profile,omitempty\"`" + ` Security []Hl7FhirCoding ` + "`json:\"security,omitempty\"`" + ` Tag []Hl7FhirCoding ` + "`json:\"tag,omitempty\"`" + ` FhirVersion string ` + "`json:\"fhirVersion,omitempty\"`" + ` } type Hl7FhirCoding struct { System string ` + "`json:\"system,omitempty\"`" + ` Version string ` + "`json:\"version,omitempty\"`" + ` Code string ` + "`json:\"code,omitempty\"`" + ` Display string ` + "`json:\"display,omitempty\"`" + ` UserSelected *bool ` + "`json:\"userSelected,omitempty\"`" + ` } type Hl7FhirCodeableConcept struct { Coding []Hl7FhirCoding ` + "`json:\"coding,omitempty\"`" + ` Text string ` + "`json:\"text,omitempty\"`" + ` } type Hl7FhirReference struct { Reference string ` + "`json:\"reference,omitempty\"`" + ` Type string ` + "`json:\"type,omitempty\"`" + ` Identifier Hl7FhirIdentifier ` + "`json:\"identifier,omitempty\"`" + ` Display string ` + "`json:\"display,omitempty\"`" + ` } type Hl7FhirIdentifier struct { Use string ` + "`json:\"use,omitempty\" validate:\"omitempty,oneof=usual official temp secondary old\"`" + ` Type Hl7FhirCodeableConcept ` + "`json:\"type,omitempty\"`" + ` System string ` + "`json:\"system,omitempty\" validate:\"omitempty,url\"`" + ` Value string ` + "`json:\"value,omitempty\"`" + ` Period Hl7FhirPeriod ` + "`json:\"period,omitempty\"`" + ` Assigner Hl7FhirReference ` + "`json:\"assigner,omitempty\"`" + ` } type Hl7FhirPeriod struct { Start string ` + "`json:\"start,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + ` End string ` + "`json:\"end,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + ` } // HL7 FHIR OperationOutcome for error handling type Hl7FhirOperationOutcome struct { ResourceType string ` + "`json:\"resourceType\"`" + ` ID string ` + "`json:\"id,omitempty\"`" + ` Meta Hl7FhirMeta ` + "`json:\"meta,omitempty\"`" + ` Issue []Hl7FhirOperationOutcomeIssue ` + "`json:\"issue\"`" + ` } type Hl7FhirOperationOutcomeIssue struct { Severity string ` + "`json:\"severity\" validate:\"required,oneof=fatal error warning information\"`" + ` Code string ` + "`json:\"code\" validate:\"required\"`" + ` Details Hl7FhirCodeableConcept ` + "`json:\"details,omitempty\"`" + ` Diagnostics string ` + "`json:\"diagnostics,omitempty\"`" + ` Location []string ` + "`json:\"location,omitempty\"`" + ` Expression []string ` + "`json:\"expression,omitempty\"`" + ` } // HL7 FHIR Bundle for search results type Hl7FhirBundleResponse struct { ResourceType string ` + "`json:\"resourceType\"`" + ` ID string ` + "`json:\"id,omitempty\"`" + ` Meta Hl7FhirMeta ` + "`json:\"meta,omitempty\"`" + ` Type string ` + "`json:\"type\" validate:\"required,oneof=document message transaction transaction-response batch batch-response history searchset collection\"`" + ` Timestamp string ` + "`json:\"timestamp,omitempty\"`" + ` Total int ` + "`json:\"total,omitempty\"`" + ` Link []Hl7FhirBundleLink ` + "`json:\"link,omitempty\"`" + ` Entry []Hl7FhirBundleEntry ` + "`json:\"entry,omitempty\"`" + ` Signature Hl7FhirSignature ` + "`json:\"signature,omitempty\"`" + ` SearchParams map[string]string ` + "`json:\"-\"`" + ` // For internal use } type Hl7FhirBundleLink struct { Relation string ` + "`json:\"relation\" validate:\"required\"`" + ` URL string ` + "`json:\"url\" validate:\"required,url\"`" + ` } type Hl7FhirBundleEntry struct { Link []Hl7FhirBundleLink ` + "`json:\"link,omitempty\"`" + ` FullURL string ` + "`json:\"fullUrl,omitempty\" validate:\"omitempty,url\"`" + ` Resource interface{} ` + "`json:\"resource,omitempty\"`" + ` Search Hl7FhirBundleEntrySearch ` + "`json:\"search,omitempty\"`" + ` Request Hl7FhirBundleEntryRequest ` + "`json:\"request,omitempty\"`" + ` Response Hl7FhirBundleEntryResponse` + "`json:\"response,omitempty\"`" + ` } type Hl7FhirBundleEntrySearch struct { Mode string ` + "`json:\"mode,omitempty\" validate:\"omitempty,oneof=match include outcome\"`" + ` Score float64 ` + "`json:\"score,omitempty\"`" + ` } type Hl7FhirBundleEntryRequest struct { Method string ` + "`json:\"method\" validate:\"required,oneof=GET HEAD POST PUT DELETE PATCH\"`" + ` URL string ` + "`json:\"url\" validate:\"required\"`" + ` IfNoneMatch string ` + "`json:\"ifNoneMatch,omitempty\"`" + ` IfModifiedSince string ` + "`json:\"ifModifiedSince,omitempty\"`" + ` IfMatch string ` + "`json:\"ifMatch,omitempty\"`" + ` IfNoneExist string ` + "`json:\"ifNoneExist,omitempty\"`" + ` } type Hl7FhirBundleEntryResponse struct { Status string ` + "`json:\"status\" validate:\"required\"`" + ` Location string ` + "`json:\"location,omitempty\" validate:\"omitempty,url\"`" + ` ETag string ` + "`json:\"etag,omitempty\"`" + ` LastModified string ` + "`json:\"lastModified,omitempty\"`" + ` Outcome interface{} ` + "`json:\"outcome,omitempty\"`" + ` } type Hl7FhirSignature struct { Type []Hl7FhirCoding ` + "`json:\"type\" validate:\"required,min=1\"`" + ` When string ` + "`json:\"when\" validate:\"required,datetime=2006-01-02T15:04:05Z07:00\"`" + ` Who Hl7FhirReference` + "`json:\"who\" validate:\"required\"`" + ` OnBehalfOf Hl7FhirReference` + "`json:\"onBehalfOf,omitempty\"`" + ` TargetFormat string ` + "`json:\"targetFormat,omitempty\"`" + ` SigFormat string ` + "`json:\"sigFormat,omitempty\"`" + ` Data string ` + "`json:\"data,omitempty\"`" + ` } // Base request/response structures with HL7 FHIR integration type BaseRequest struct { RequestID string ` + "`json:\"request_id,omitempty\"`" + ` Timestamp time.Time ` + "`json:\"timestamp,omitempty\"`" + ` } type BaseResponse struct { Status string ` + "`json:\"status\"`" + ` Message string ` + "`json:\"message\"`" + ` Data interface{} ` + "`json:\"data,omitempty\"`" + ` Error *ErrorResponse ` + "`json:\"error,omitempty\"`" + ` Metadata *ResponseMetadata ` + "`json:\"metadata,omitempty\"`" + ` } type ErrorResponse struct { Code string ` + "`json:\"code\"`" + ` Message string ` + "`json:\"message\"`" + ` Details string ` + "`json:\"details,omitempty\"`" + ` } type ResponseMetadata struct { Timestamp time.Time ` + "`json:\"timestamp\"`" + ` Version string ` + "`json:\"version\"`" + ` RequestID string ` + "`json:\"request_id,omitempty\"`" + ` Path string ` + "`json:\"path,omitempty\"`" + ` Depth int ` + "`json:\"depth,omitempty\"`" + ` FhirResource string ` + "`json:\"fhir_resource,omitempty\"`" + ` FhirVersion string ` + "`json:\"fhir_version,omitempty\"`" + ` FhirProfile string ` + "`json:\"fhir_profile,omitempty\"`" + ` } // ` + data.Name + ` Response Structure with HL7 FHIR integration type ` + data.Name + `Response struct { Hl7FhirResource BaseResponse } // Generic HL7 FHIR Response type Hl7FhirResponse struct { ResourceType string ` + "`json:\"resourceType\"`" + ` ID string ` + "`json:\"id,omitempty\"`" + ` Meta Hl7FhirMeta ` + "`json:\"meta,omitempty\"`" + ` Content map[string]interface{} ` + "`json:\"-\"`" + ` // For dynamic content }` // Add CRUD request structures based on methods if data.HasPost { modelContent += generateHl7FhirCreateRequestModel(data) } if data.HasPut { modelContent += generateHl7FhirUpdateRequestModel(data) } if data.HasPatch { modelContent += generateHl7FhirPatchRequestModel(data) } // Add common HL7 FHIR data types and validation helpers modelContent += generateHl7FhirCommonDataTypes(data) modelContent += generateHl7FhirValidationHelpers(data) writeFile(filepath.Join(modelDir, data.NameLower+".go"), modelContent) } func generateHl7FhirCreateRequestModel(data Hl7FhirHandlerData) string { profileValidation := "" if data.Profile != "" { profileValidation = ` // Validate profile-specific constraints if err := r.ValidateProfile("` + data.Profile + `"); err != nil { return err }` } return ` // ` + data.Name + ` CREATE Request Structure with HL7 FHIR ` + data.FhirVersion + ` Validation type ` + data.Name + `CreateRequest struct { BaseRequest ResourceType string ` + "`json:\"resourceType\" binding:\"required\" validate:\"required,eq=` + data.FhirResource + `\"`" + ` // Core HL7 FHIR ` + data.FhirResource + ` fields - customize based on specific resource // FHIR Version: ` + data.FhirVersion + ` // Path: ` + data.Category + ` Meta Hl7FhirMeta ` + "`json:\"meta,omitempty\"`" + ` ImplicitRules string ` + "`json:\"implicitRules,omitempty\" validate:\"omitempty,url\"`" + ` Language string ` + "`json:\"language,omitempty\" validate:\"omitempty,len=2\"`" + ` Text Hl7FhirNarrative ` + "`json:\"text,omitempty\"`" + ` Contained []interface{} ` + "`json:\"contained,omitempty\"`" + ` Extension []Hl7FhirExtension ` + "`json:\"extension,omitempty\"`" + ` ModifierExtension []Hl7FhirExtension ` + "`json:\"modifierExtension,omitempty\"`" + ` // Resource-specific fields (customize per resource type) Identifier []Hl7FhirIdentifier ` + "`json:\"identifier,omitempty\" validate:\"dive\"`" + ` Active *bool ` + "`json:\"active,omitempty\"`" + ` Name []Hl7FhirHumanName ` + "`json:\"name,omitempty\" validate:\"dive\"`" + ` Telecom []Hl7FhirContactPoint ` + "`json:\"telecom,omitempty\" validate:\"dive\"`" + ` Gender string ` + "`json:\"gender,omitempty\" validate:\"omitempty,oneof=male female other unknown\"`" + ` BirthDate string ` + "`json:\"birthDate,omitempty\" validate:\"omitempty,datetime=2006-01-02\"`" + ` Address []Hl7FhirAddress ` + "`json:\"address,omitempty\" validate:\"dive\"`" + ` MaritalStatus Hl7FhirCodeableConcept ` + "`json:\"maritalStatus,omitempty\"`" + ` Contact []Hl7FhirPatientContact ` + "`json:\"contact,omitempty\"`" + ` Communication []Hl7FhirPatientCommunication ` + "`json:\"communication,omitempty\"`" + ` GeneralPractitioner []Hl7FhirReference ` + "`json:\"generalPractitioner,omitempty\"`" + ` ManagingOrganization Hl7FhirReference ` + "`json:\"managingOrganization,omitempty\"`" + ` } // Additional HL7 FHIR data types for ` + data.FhirResource + ` type Hl7FhirNarrative struct { Status string ` + "`json:\"status\" validate:\"required,oneof=generated extensions additional empty\"`" + ` Div string ` + "`json:\"div\" validate:\"required\"`" + ` } type Hl7FhirExtension struct { URL string ` + "`json:\"url\" validate:\"required,url\"`" + ` Value interface{} ` + "`json:\"value,omitempty\"`" + ` // Can be various types } type Hl7FhirHumanName struct { Use string ` + "`json:\"use,omitempty\" validate:\"omitempty,oneof=usual official temp nickname anonymous old maiden\"`" + ` Text string ` + "`json:\"text,omitempty\"`" + ` Family string ` + "`json:\"family,omitempty\"`" + ` Given []string ` + "`json:\"given,omitempty\"`" + ` Prefix []string ` + "`json:\"prefix,omitempty\"`" + ` Suffix []string ` + "`json:\"suffix,omitempty\"`" + ` Period Hl7FhirPeriod ` + "`json:\"period,omitempty\"`" + ` } type Hl7FhirContactPoint struct { System string ` + "`json:\"system,omitempty\" validate:\"omitempty,oneof=phone fax email pager url sms other\"`" + ` Value string ` + "`json:\"value,omitempty\"`" + ` Use string ` + "`json:\"use,omitempty\" validate:\"omitempty,oneof=home work temp old mobile\"`" + ` Rank int ` + "`json:\"rank,omitempty\" validate:\"omitempty,min=1\"`" + ` Period Hl7FhirPeriod ` + "`json:\"period,omitempty\"`" + ` } type Hl7FhirAddress struct { Use string ` + "`json:\"use,omitempty\" validate:\"omitempty,oneof=home work temp old billing\"`" + ` Type string ` + "`json:\"type,omitempty\" validate:\"omitempty,oneof=postal physical both\"`" + ` Text string ` + "`json:\"text,omitempty\"`" + ` Line []string ` + "`json:\"line,omitempty\"`" + ` City string ` + "`json:\"city,omitempty\"`" + ` District string ` + "`json:\"district,omitempty\"`" + ` State string ` + "`json:\"state,omitempty\"`" + ` PostalCode string ` + "`json:\"postalCode,omitempty\"`" + ` Country string ` + "`json:\"country,omitempty\" validate:\"omitempty,len=2\"`" + ` Period Hl7FhirPeriod ` + "`json:\"period,omitempty\"`" + ` } type Hl7FhirPatientContact struct { Relationship []Hl7FhirCodeableConcept ` + "`json:\"relationship,omitempty\"`" + ` Name Hl7FhirHumanName ` + "`json:\"name,omitempty\"`" + ` Telecom []Hl7FhirContactPoint ` + "`json:\"telecom,omitempty\"`" + ` Address Hl7FhirAddress ` + "`json:\"address,omitempty\"`" + ` Gender string ` + "`json:\"gender,omitempty\" validate:\"omitempty,oneof=male female other unknown\"`" + ` Organization Hl7FhirReference ` + "`json:\"organization,omitempty\"`" + ` Period Hl7FhirPeriod ` + "`json:\"period,omitempty\"`" + ` } type Hl7FhirPatientCommunication struct { Language Hl7FhirCodeableConcept ` + "`json:\"language\" validate:\"required\"`" + ` Preferred *bool ` + "`json:\"preferred,omitempty\"`" + ` } // ValidateHl7Fhir validates the ` + data.Name + `CreateRequest with HL7 FHIR ` + data.FhirVersion + ` business rules func (r *` + data.Name + `CreateRequest) ValidateHl7Fhir() error { if r.ResourceType != "` + data.FhirResource + `" { return fmt.Errorf("invalid resourceType: expected ` + data.FhirResource + `, got %s", r.ResourceType) } // Validate narrative if present if r.Text.Status != "" { if r.Text.Div == "" { return fmt.Errorf("narrative div is required when status is provided") } if !isValidXhtml(r.Text.Div) { return fmt.Errorf("narrative div must be valid XHTML") } } // Validate identifiers for i, identifier := range r.Identifier { if identifier.System != "" && identifier.Value == "" { return fmt.Errorf("identifier[%d]: value is required when system is provided", i) } } // Validate extensions for i, ext := range r.Extension { if ext.URL == "" { return fmt.Errorf("extension[%d]: url is required", i) } }` + profileValidation + ` // Path: ` + data.Category + ` return nil } // ValidateProfile validates profile-specific constraints func (r *` + data.Name + `CreateRequest) ValidateProfile(profile string) error { switch profile { case "USCore": return r.validateUSCoreProfile() case "AUBase": return r.validateAUBaseProfile() case "UKCore": return r.validateUKCoreProfile() case "CABaseline": return r.validateCABaselineProfile() case "InternationalPatientSummary": return r.validateIPSProfile() default: return nil // No specific profile validation } } func (r *` + data.Name + `CreateRequest) validateUSCoreProfile() error { // US Core Patient profile requirements if len(r.Identifier) == 0 { return fmt.Errorf("US Core Patient requires at least one identifier") } if len(r.Name) == 0 { return fmt.Errorf("US Core Patient requires at least one name") } if r.Gender == "" { return fmt.Errorf("US Core Patient requires gender") } return nil } func (r *` + data.Name + `CreateRequest) validateAUBaseProfile() error { // AU Base Patient profile requirements // Add Australian-specific validation rules return nil } func (r *` + data.Name + `CreateRequest) validateUKCoreProfile() error { // UK Core Patient profile requirements // Add UK-specific validation rules return nil } func (r *` + data.Name + `CreateRequest) validateCABaselineProfile() error { // CA Baseline Patient profile requirements // Add Canadian-specific validation rules return nil } func (r *` + data.Name + `CreateRequest) validateIPSProfile() error { // International Patient Summary profile requirements // Add IPS-specific validation rules return nil } // ToJSON converts struct to JSON string func (r *` + data.Name + `CreateRequest) ToJSON() (string, error) { data, err := json.Marshal(r) return string(data), err }` } func generateHl7FhirValidationHelpers(data Hl7FhirHandlerData) string { return ` // HL7 FHIR validation helper functions func isValidXhtml(xhtml string) bool { // Basic XHTML validation - in production, use proper XML parser return strings.HasPrefix(xhtml, "