Files
antrean-anjungan/tools/fhir/generate-handler.go
2025-08-26 09:47:42 +07:00

2730 lines
120 KiB
Go

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, "<div") && strings.HasSuffix(xhtml, "</div>")
}
func isValidHl7FhirDate(date string) bool {
// FHIR date format: YYYY, YYYY-MM, or YYYY-MM-DD
patterns := []string{
"^[0-9]{4}$", // Year only
"^[0-9]{4}-[0-9]{2}$", // Year-Month
"^[0-9]{4}-[0-9]{2}-[0-9]{2}$", // Full date
}
for _, pattern := range patterns {
matched, _ := regexp.MatchString(pattern, date)
if matched {
return true
}
}
return false
}
func isValidHl7FhirDateTime(datetime string) bool {
// FHIR datetime format with timezone
pattern := "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$"
matched, _ := regexp.MatchString(pattern, datetime)
return matched
}
func isValidHl7FhirID(id string) bool {
// FHIR ID: 1-64 characters, alphanumeric, dash, dot
if len(id) < 1 || len(id) > 64 {
return false
}
pattern := "^[A-Za-z0-9\\-\\.]{1,64}$"
matched, _ := regexp.MatchString(pattern, id)
return matched
}
func isValidHl7FhirUri(uri string) bool {
// Basic URI validation - in production, use proper URI parser
pattern := "^[a-zA-Z][a-zA-Z0-9+.-]*:"
matched, _ := regexp.MatchString(pattern, uri)
return matched
}
func isValidHl7FhirCode(code string) bool {
// FHIR code: no whitespace, control chars
pattern := "^[^\\s\\x00-\\x1F\\x7F]+$"
matched, _ := regexp.MatchString(pattern, code)
return matched && len(code) > 0
}
func isValidLanguageCode(lang string) bool {
// BCP 47 language code (simplified validation)
if len(lang) < 2 || len(lang) > 8 {
return false
}
pattern := "^[a-z]{2,3}(-[A-Z]{2})?(-[a-z]{2,8})*$"
matched, _ := regexp.MatchString(pattern, lang)
return matched
}
// GetHl7FhirPathInfo returns information about the multi-level HL7 FHIR path
func GetHl7FhirPathInfo() map[string]interface{} {
return map[string]interface{}{
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"fhir_profile": "` + data.Profile + `",
"path": "` + data.Category + `",
"depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `,
"parts": []string{` + `"` + strings.Join(data.CategoryParts, `", "`) + `"` + `},
"base_url": "http://hl7.org/fhir/` + strings.ToLower(data.FhirVersion) + `",
"profile_url": getStandardProfileUrl("` + data.Profile + `", "` + data.FhirResource + `"),
"specification": "http://hl7.org/fhir/` + strings.ToLower(data.FhirVersion) + `/` + strings.ToLower(data.FhirResource) + `.html",
}
}
func getStandardProfileUrl(profile, resource string) string {
profileUrls := map[string]string{
"USCore": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-" + strings.ToLower(resource),
"AUBase": "http://hl7.org.au/fhir/base/StructureDefinition/au-" + strings.ToLower(resource),
"UKCore": "https://fhir.hl7.org.uk/StructureDefinition/UKCore-" + resource,
"CABaseline": "http://hl7.org/fhir/ca/baseline/StructureDefinition/profile-" + strings.ToLower(resource),
"InternationalPatientSummary": "http://hl7.org/fhir/uv/ips/StructureDefinition/" + resource + "-uv-ips",
}
if url, exists := profileUrls[profile]; exists {
return url
}
return ""
}
// Common terminology system URLs
const (
SNOMED_CT_URL = "http://snomed.info/sct"
LOINC_URL = "http://loinc.org"
ICD10_URL = "http://hl7.org/fhir/sid/icd-10"
ICD11_URL = "http://id.who.int/icd/release/11/mms"
RXNORM_URL = "http://www.nlm.nih.gov/research/umls/rxnorm"
CPT_URL = "http://www.ama-assn.org/go/cpt"
UCUM_URL = "http://unitsofmeasure.org"
HL7_V3_URL = "http://terminology.hl7.org/CodeSystem/v3-"
HL7_V2_URL = "http://terminology.hl7.org/CodeSystem/v2-"
)`
}
func generateOptimizedHl7FhirUpdateMethod(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 `
// Update` + data.Name + ` updates (replaces) an existing HL7 FHIR ` + data.FhirResource + ` resource
// @Summary Update (replace) an existing HL7 FHIR ` + data.FhirResource + ` resource
// @Description Update an existing ` + 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 If-Match header string false "Version-aware update (ETag)"
// @Param Prefer header string false "Return preference (return=minimal, return=representation, return=OperationOutcome)"
// @Param id path string true "` + data.FhirResource + ` resource ID"
// @Param request body models.` + data.Name + `UpdateRequest true "` + data.FhirResource + ` FHIR resource update request"
// @Success 200 {object} models.` + data.Name + `Response "` + data.FhirResource + ` resource updated successfully"
// @Failure 400 {object} models.Hl7FhirOperationOutcome "Bad request - validation error"
// @Failure 404 {object} models.Hl7FhirOperationOutcome "Resource not found"
// @Failure 409 {object} models.Hl7FhirOperationOutcome "Version conflict"
// @Failure 412 {object} models.Hl7FhirOperationOutcome "Precondition failed"
// @Failure 422 {object} models.Hl7FhirOperationOutcome "Unprocessable entity - FHIR validation error"
// @Failure 500 {object} models.Hl7FhirOperationOutcome "Internal server error"
// @Router /api/v1/` + routePath + `/{id} [put]
func (h *` + data.Name + `Handler) Update` + data.Name + `(c *gin.Context) {
requestID := uuid.New().String()
startTime := time.Now()
id := c.Param("id")
h.logger.Info("Updating 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 + `",
"resource_id": id,
"category_path": "` + data.Category + `",
"directory_depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `,
"content_type": c.GetHeader("Content-Type"),
"if_match": c.GetHeader("If-Match"),
"prefer": c.GetHeader("Prefer"),
})
if id == "" {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "required",
"Resource ID is required", "", requestID)
return
}
if !isValidHl7FhirID(id) {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Invalid resource ID format", "", requestID)
return
}
var req models.` + data.Name + `UpdateRequest
req.RequestID = requestID
req.Timestamp = startTime
req.ID = id
if err := c.ShouldBindJSON(&req); err != nil {
h.logger.Error("Failed to bind HL7 FHIR JSON for update", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"path": "` + routePath + `",
})
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "structure",
"Invalid FHIR resource structure", err.Error(), requestID)
return
}
// Validate resource ID matches URL parameter
if req.ID != "" && req.ID != id {
h.logger.Error("Resource ID mismatch", map[string]interface{}{
"url_id": id,
"resource_id": req.ID,
"request_id": requestID,
})
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Resource ID in body must match URL parameter", "", requestID)
return
}
req.ID = id // Ensure ID is set
if err := req.ValidateHl7Fhir(); err != nil {
h.logger.Error("HL7 FHIR update validation failed", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"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 + `",
"resource_id": id,
"path": "` + routePath + `",
})
h.sendHl7FhirErrorResponse(c, http.StatusUnprocessableEntity, "business-rule",
"Profile validation failed", err.Error(), requestID)
return
}
}
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 + `",
"resource_id": id,
"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()
endpoint := fmt.Sprintf("` + strings.Replace(data.PutEndpoint, "{id}", "%s", 1) + `", id)
var fhirResponse models.Hl7FhirResponse
// Handle If-Match header for version-aware updates
ifMatch := c.GetHeader("If-Match")
if ifMatch != "" {
req.Meta.VersionId = parseETag(ifMatch)
}
if err := h.service.UpdateResource(ctx, endpoint, req, &fhirResponse); err != nil {
h.logger.Error("Failed to update HL7 FHIR resource", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"endpoint": endpoint,
"path": "` + routePath + `",
})
statusCode, errorCode := h.categorizeHl7FhirError(err)
h.sendHl7FhirErrorResponse(c, statusCode, errorCode,
"Failed to update ` + data.FhirResource + ` resource", err.Error(), requestID)
return
}
if fhirResponse.ResourceType == "OperationOutcome" {
h.logger.Warn("HL7 FHIR server returned OperationOutcome for update", map[string]interface{}{
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"path": "` + routePath + `",
"outcome": fhirResponse,
})
h.sendHl7FhirOperationOutcome(c, http.StatusUnprocessableEntity, fhirResponse, requestID)
return
}
duration := time.Since(startTime)
h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource updated successfully", map[string]interface{}{
"request_id": requestID,
"duration": duration.String(),
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": 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.StatusOK)
return
}
h.sendHl7FhirSuccessResponse(c, http.StatusOK, "` + data.FhirResource + ` resource updated successfully",
fhirResponse, requestID)
}`
}
func generateOptimizedHl7FhirPatchMethod(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 `
// Patch` + data.Name + ` partially updates an existing HL7 FHIR ` + data.FhirResource + ` resource
// @Summary Patch (partial update) an existing HL7 FHIR ` + data.FhirResource + ` resource
// @Description Partially update an existing ` + data.FhirResource + ` resource compliant with HL7 FHIR ` + data.FhirVersion + `` + profileTag + ` using JSON Patch
// @Description FHIR Resource: ` + data.FhirResource + ` | Version: ` + data.FhirVersion + ` | Path: ` + data.Category + `
// @Tags ` + tagName + `
// @Accept json-patch+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/json-patch+json)"
// @Param If-Match header string false "Version-aware patch (ETag)"
// @Param Prefer header string false "Return preference (return=minimal, return=representation, return=OperationOutcome)"
// @Param id path string true "` + data.FhirResource + ` resource ID"
// @Param request body models.` + data.Name + `PatchRequest true "` + data.FhirResource + ` FHIR resource patch request"
// @Success 200 {object} models.` + data.Name + `Response "` + data.FhirResource + ` resource patched successfully"
// @Failure 400 {object} models.Hl7FhirOperationOutcome "Bad request - validation error"
// @Failure 404 {object} models.Hl7FhirOperationOutcome "Resource not found"
// @Failure 409 {object} models.Hl7FhirOperationOutcome "Version conflict"
// @Failure 412 {object} models.Hl7FhirOperationOutcome "Precondition failed"
// @Failure 422 {object} models.Hl7FhirOperationOutcome "Unprocessable entity - FHIR validation error"
// @Failure 500 {object} models.Hl7FhirOperationOutcome "Internal server error"
// @Router /api/v1/` + routePath + `/{id} [patch]
func (h *` + data.Name + `Handler) Patch` + data.Name + `(c *gin.Context) {
requestID := uuid.New().String()
startTime := time.Now()
id := c.Param("id")
h.logger.Info("Patching 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 + `",
"resource_id": id,
"category_path": "` + data.Category + `",
"directory_depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `,
"content_type": c.GetHeader("Content-Type"),
"if_match": c.GetHeader("If-Match"),
"prefer": c.GetHeader("Prefer"),
})
if id == "" {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "required",
"Resource ID is required", "", requestID)
return
}
if !isValidHl7FhirID(id) {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Invalid resource ID format", "", requestID)
return
}
// Validate Content-Type for patch operations
contentType := c.GetHeader("Content-Type")
if !strings.Contains(contentType, "application/json-patch+json") &&
!strings.Contains(contentType, "application/json") {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "not-supported",
"Unsupported content type for patch operation", "", requestID)
return
}
var req models.` + data.Name + `PatchRequest
req.RequestID = requestID
req.Timestamp = startTime
req.ID = id
if err := c.ShouldBindJSON(&req); err != nil {
h.logger.Error("Failed to bind HL7 FHIR patch JSON", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"path": "` + routePath + `",
})
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "structure",
"Invalid FHIR patch structure", err.Error(), requestID)
return
}
if err := req.ValidateHl7FhirPatch(); err != nil {
h.logger.Error("HL7 FHIR patch validation failed", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"path": "` + routePath + `",
})
h.sendHl7FhirErrorResponse(c, http.StatusUnprocessableEntity, "business-rule",
"HL7 FHIR patch validation failed", err.Error(), requestID)
return
}
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 + `",
"resource_id": id,
"path": "` + routePath + `",
})
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "structure",
"Patch structure validation failed", h.formatValidationError(err), requestID)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
defer cancel()
endpoint := fmt.Sprintf("` + strings.Replace(data.PatchEndpoint, "{id}", "%s", 1) + `", id)
var fhirResponse models.Hl7FhirResponse
// Handle If-Match header for version-aware patches
ifMatch := c.GetHeader("If-Match")
if ifMatch != "" {
req.VersionId = parseETag(ifMatch)
}
if err := h.service.PatchResource(ctx, endpoint, req, &fhirResponse); err != nil {
h.logger.Error("Failed to patch HL7 FHIR resource", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"endpoint": endpoint,
"path": "` + routePath + `",
})
statusCode, errorCode := h.categorizeHl7FhirError(err)
h.sendHl7FhirErrorResponse(c, statusCode, errorCode,
"Failed to patch ` + data.FhirResource + ` resource", err.Error(), requestID)
return
}
if fhirResponse.ResourceType == "OperationOutcome" {
h.logger.Warn("HL7 FHIR server returned OperationOutcome for patch", map[string]interface{}{
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"path": "` + routePath + `",
"outcome": fhirResponse,
})
h.sendHl7FhirOperationOutcome(c, http.StatusUnprocessableEntity, fhirResponse, requestID)
return
}
duration := time.Since(startTime)
h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource patched successfully", map[string]interface{}{
"request_id": requestID,
"duration": duration.String(),
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"patch_ops": len(req.Patches),
"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.StatusOK)
return
}
h.sendHl7FhirSuccessResponse(c, http.StatusOK, "` + data.FhirResource + ` resource patched successfully",
fhirResponse, requestID)
}`
}
func generateOptimizedHl7FhirDeleteMethod(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 `
// Delete` + data.Name + ` deletes an existing HL7 FHIR ` + data.FhirResource + ` resource
// @Summary Delete an existing HL7 FHIR ` + data.FhirResource + ` resource
// @Description Delete an existing ` + 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 If-Match header string false "Version-aware delete (ETag)"
// @Param id path string true "` + data.FhirResource + ` resource ID"
// @Success 204 "` + data.FhirResource + ` resource deleted successfully"
// @Success 200 {object} models.Hl7FhirOperationOutcome "Delete operation outcome"
// @Failure 400 {object} models.Hl7FhirOperationOutcome "Bad request - invalid ID"
// @Failure 404 {object} models.Hl7FhirOperationOutcome "Resource not found"
// @Failure 409 {object} models.Hl7FhirOperationOutcome "Version conflict"
// @Failure 412 {object} models.Hl7FhirOperationOutcome "Precondition failed"
// @Failure 500 {object} models.Hl7FhirOperationOutcome "Internal server error"
// @Router /api/v1/` + routePath + `/{id} [delete]
func (h *` + data.Name + `Handler) Delete` + data.Name + `(c *gin.Context) {
requestID := uuid.New().String()
startTime := time.Now()
id := c.Param("id")
h.logger.Info("Deleting 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 + `",
"resource_id": id,
"category_path": "` + data.Category + `",
"directory_depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `,
"if_match": c.GetHeader("If-Match"),
})
if id == "" {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "required",
"Resource ID is required", "", requestID)
return
}
if !isValidHl7FhirID(id) {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Invalid resource ID format", "", requestID)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
defer cancel()
endpoint := fmt.Sprintf("` + strings.Replace(data.DeleteEndpoint, "{id}", "%s", 1) + `", id)
// Handle If-Match header for version-aware deletes
ifMatch := c.GetHeader("If-Match")
versionId := ""
if ifMatch != "" {
versionId = parseETag(ifMatch)
}
deleteResult, err := h.service.DeleteResource(ctx, endpoint, versionId)
if err != nil {
h.logger.Error("Failed to delete HL7 FHIR resource", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"endpoint": endpoint,
"path": "` + routePath + `",
})
statusCode, errorCode := h.categorizeHl7FhirError(err)
h.sendHl7FhirErrorResponse(c, statusCode, errorCode,
"Failed to delete ` + data.FhirResource + ` resource", err.Error(), requestID)
return
}
duration := time.Since(startTime)
h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource deleted successfully", map[string]interface{}{
"request_id": requestID,
"duration": duration.String(),
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"delete_result": deleteResult,
"path": "` + routePath + `",
})
// FHIR delete can return either 204 (No Content) or 200 with OperationOutcome
if deleteResult.OperationOutcome != nil {
// Server returned an OperationOutcome (successful delete with info)
c.Header("Content-Type", "application/fhir+json; fhirVersion=` + data.FhirVersion + `")
c.JSON(http.StatusOK, deleteResult.OperationOutcome)
return
}
// Standard successful delete - no content
c.Status(http.StatusNoContent)
}`
}
func generateOptimizedHl7FhirGetMethod(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 `
// Get` + data.Name + ` retrieves a specific HL7 FHIR ` + data.FhirResource + ` resource by ID
// @Summary Get a specific HL7 FHIR ` + data.FhirResource + ` resource by ID
// @Description Retrieve a specific ` + 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 If-None-Match header string false "Conditional read (ETag)"
// @Param If-Modified-Since header string false "Conditional read (last modified)"
// @Param _summary query string false "Summary mode (true, text, data, count, false)"
// @Param _elements query string false "Elements to return (comma-separated)"
// @Param _format query string false "Response format override (json, xml)"
// @Param id path string true "` + data.FhirResource + ` resource ID"
// @Success 200 {object} models.` + data.Name + `Response "` + data.FhirResource + ` resource retrieved successfully"
// @Success 304 "Not modified (conditional read)"
// @Failure 400 {object} models.Hl7FhirOperationOutcome "Bad request - invalid ID"
// @Failure 404 {object} models.Hl7FhirOperationOutcome "Resource not found"
// @Failure 410 {object} models.Hl7FhirOperationOutcome "Resource deleted"
// @Failure 500 {object} models.Hl7FhirOperationOutcome "Internal server error"
// @Router /api/v1/` + routePath + `/{id} [get]
func (h *` + data.Name + `Handler) Get` + data.Name + `(c *gin.Context) {
requestID := uuid.New().String()
startTime := time.Now()
id := c.Param("id")
h.logger.Info("Getting 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 + `",
"resource_id": id,
"category_path": "` + data.Category + `",
"directory_depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `,
"accept": c.GetHeader("Accept"),
"if_none_match": c.GetHeader("If-None-Match"),
"if_modified_since": c.GetHeader("If-Modified-Since"),
"summary": c.Query("_summary"),
"elements": c.Query("_elements"),
"format": c.Query("_format"),
})
if id == "" {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "required",
"Resource ID is required", "", requestID)
return
}
if !isValidHl7FhirID(id) {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Invalid resource ID format", "", requestID)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
defer cancel()
endpoint := fmt.Sprintf("` + strings.Replace(data.GetEndpoint, "{id}", "%s", 1) + `", id)
// Build query parameters for read options
queryParams := make(map[string]string)
if summary := c.Query("_summary"); summary != "" {
if summary == "true" || summary == "text" || summary == "data" || summary == "count" || summary == "false" {
queryParams["_summary"] = summary
}
}
if elements := c.Query("_elements"); elements != "" {
queryParams["_elements"] = elements
}
if format := c.Query("_format"); format != "" {
queryParams["_format"] = format
}
// Handle conditional read headers
ifNoneMatch := c.GetHeader("If-None-Match")
ifModifiedSince := c.GetHeader("If-Modified-Since")
var fhirResponse models.Hl7FhirResponse
readResult, err := h.service.GetResource(ctx, endpoint, queryParams, ifNoneMatch, ifModifiedSince, &fhirResponse)
if err != nil {
h.logger.Error("Failed to get HL7 FHIR resource", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"endpoint": endpoint,
"path": "` + routePath + `",
})
statusCode, errorCode := h.categorizeHl7FhirError(err)
h.sendHl7FhirErrorResponse(c, statusCode, errorCode,
"Failed to get ` + data.FhirResource + ` resource", err.Error(), requestID)
return
}
// Handle conditional read responses
if readResult.NotModified {
h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource not modified", map[string]interface{}{
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"path": "` + routePath + `",
})
c.Status(http.StatusNotModified)
return
}
if fhirResponse.ResourceType == "OperationOutcome" {
h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource not found", map[string]interface{}{
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"resource_id": id,
"path": "` + routePath + `",
"outcome": fhirResponse,
})
h.sendHl7FhirOperationOutcome(c, http.StatusNotFound, fhirResponse, requestID)
return
}
duration := time.Since(startTime)
h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource retrieved successfully", map[string]interface{}{
"request_id": requestID,
"duration": duration.String(),
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"version_id": fhirResponse.Meta.VersionId,
"path": "` + routePath + `",
})
// Set response headers
if fhirResponse.Meta.VersionId != "" {
c.Header("ETag", fmt.Sprintf("W/\"%s\"", fhirResponse.Meta.VersionId))
}
if fhirResponse.Meta.LastUpdated != "" {
c.Header("Last-Modified", fhirResponse.Meta.LastUpdated)
}
h.sendHl7FhirSuccessResponse(c, http.StatusOK, "` + data.FhirResource + ` resource retrieved successfully",
fhirResponse, requestID)
}`
}
func generateOptimizedHl7FhirHistoryMethod(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 `
// History` + data.Name + ` retrieves the version history for a specific HL7 FHIR ` + data.FhirResource + ` resource
// @Summary Get version history for a specific HL7 FHIR ` + data.FhirResource + ` resource
// @Description Retrieve the version history for a specific ` + 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 _count query integer false "Number of history entries to return (default: 10, max: 50)"
// @Param _since query string false "Only return versions since this instant (ISO 8601)"
// @Param _at query string false "Only return versions that were current at this time (ISO 8601)"
// @Param _page query integer false "Page number for pagination (default: 1)"
// @Param _sort query string false "Sort order for history (_lastUpdated, -_lastUpdated)"
// @Param _format query string false "Response format override (json, xml)"
// @Param id path string true "` + data.FhirResource + ` resource ID"
// @Success 200 {object} models.Hl7FhirBundleResponse "` + data.FhirResource + ` resource history retrieved successfully"
// @Failure 400 {object} models.Hl7FhirOperationOutcome "Bad request - invalid parameters"
// @Failure 404 {object} models.Hl7FhirOperationOutcome "Resource not found"
// @Failure 500 {object} models.Hl7FhirOperationOutcome "Internal server error"
// @Router /api/v1/` + routePath + `/{id}/_history [get]
func (h *` + data.Name + `Handler) History` + data.Name + `(c *gin.Context) {
requestID := uuid.New().String()
startTime := time.Now()
id := c.Param("id")
h.logger.Info("Getting HL7 FHIR ` + data.FhirResource + ` resource history", map[string]interface{}{
"request_id": requestID,
"timestamp": startTime,
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"fhir_profile": "` + data.Profile + `",
"resource_id": id,
"category_path": "` + data.Category + `",
"directory_depth": ` + fmt.Sprintf("%d", data.DirectoryDepth) + `,
"query_params": c.Request.URL.Query(),
"accept": c.GetHeader("Accept"),
})
if id == "" {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "required",
"Resource ID is required", "", requestID)
return
}
if !isValidHl7FhirID(id) {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Invalid resource ID format", "", requestID)
return
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
defer cancel()
// Parse and validate history parameters
historyParams := make(map[string]string)
// Count parameter (default: 10, max: 50)
count := 10
if countStr := c.Query("_count"); countStr != "" {
if parsedCount, err := strconv.Atoi(countStr); err == nil {
if parsedCount > 0 && parsedCount <= 50 {
count = parsedCount
}
}
}
historyParams["_count"] = fmt.Sprintf("%d", count)
// Page parameter
page := 1
if pageStr := c.Query("_page"); pageStr != "" {
if parsedPage, err := strconv.Atoi(pageStr); err == nil && parsedPage > 0 {
page = parsedPage
}
}
historyParams["_page"] = fmt.Sprintf("%d", page)
// Since parameter (ISO 8601 instant)
if since := c.Query("_since"); since != "" {
if isValidHl7FhirDateTime(since) {
historyParams["_since"] = since
} else {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Invalid _since parameter format (must be ISO 8601)", "", requestID)
return
}
}
// At parameter (ISO 8601 instant)
if at := c.Query("_at"); at != "" {
if isValidHl7FhirDateTime(at) {
historyParams["_at"] = at
} else {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "invalid",
"Invalid _at parameter format (must be ISO 8601)", "", requestID)
return
}
}
// Sort parameter
if sort := c.Query("_sort"); sort != "" {
if sort == "_lastUpdated" || sort == "-_lastUpdated" {
historyParams["_sort"] = sort
} else {
h.sendHl7FhirErrorResponse(c, http.StatusBadRequest, "not-supported",
"Only _lastUpdated and -_lastUpdated sort options are supported", "", requestID)
return
}
}
// Format parameter
if format := c.Query("_format"); format != "" {
historyParams["_format"] = format
}
endpoint := fmt.Sprintf("` + strings.Replace(data.HistoryEndpoint, "{id}", "%s", 1) + `", id)
var fhirBundle models.Hl7FhirBundleResponse
if err := h.service.GetHistory(ctx, endpoint, historyParams, &fhirBundle); err != nil {
h.logger.Error("Failed to get HL7 FHIR resource history", map[string]interface{}{
"error": err.Error(),
"request_id": requestID,
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"endpoint": endpoint,
"history_params": historyParams,
"path": "` + routePath + `",
})
statusCode, errorCode := h.categorizeHl7FhirError(err)
h.sendHl7FhirErrorResponse(c, statusCode, errorCode,
"Failed to get ` + data.FhirResource + ` resource history", err.Error(), requestID)
return
}
// Ensure bundle type is history
fhirBundle.Type = "history"
fhirBundle.ID = requestID
fhirBundle.Timestamp = startTime.Format(time.RFC3339)
duration := time.Since(startTime)
h.logger.Info("HL7 FHIR ` + data.FhirResource + ` resource history retrieved successfully", map[string]interface{}{
"request_id": requestID,
"duration": duration.String(),
"fhir_resource": "` + data.FhirResource + `",
"fhir_version": "` + data.FhirVersion + `",
"resource_id": id,
"total_versions": fhirBundle.Total,
"returned_count": len(fhirBundle.Entry),
"history_params": historyParams,
"path": "` + routePath + `",
})
h.sendHl7FhirBundleResponse(c, http.StatusOK, "` + data.FhirResource + ` resource history retrieved successfully",
fhirBundle, requestID)
}`
}
func generateHl7FhirUpdateRequestModel(data Hl7FhirHandlerData) string {
return `
// ` + data.Name + ` UPDATE Request Structure with HL7 FHIR ` + data.FhirVersion + ` Validation
type ` + data.Name + `UpdateRequest struct {
BaseRequest
// Resource fields (same as create request but ID is required)
ResourceType string ` + "`json:\"resourceType\" binding:\"required\" validate:\"required,eq=` + data.FhirResource + `\"`" + `
ID string ` + "`json:\"id\" binding:\"required\" validate:\"required\"`" + `
// Include all the same fields as CreateRequest
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
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\"`" + `
}
// ValidateHl7Fhir validates the ` + data.Name + `UpdateRequest
func (r *` + data.Name + `UpdateRequest) ValidateHl7Fhir() error {
if r.ResourceType != "` + data.FhirResource + `" {
return fmt.Errorf("invalid resourceType: expected ` + data.FhirResource + `, got %s", r.ResourceType)
}
if r.ID == "" {
return fmt.Errorf("resource ID is required for update operation")
}
if !isValidHl7FhirID(r.ID) {
return fmt.Errorf("invalid resource ID format")
}
// Same validation as create request
return nil
}
// ValidateProfile validates profile-specific constraints for update
func (r *` + data.Name + `UpdateRequest) ValidateProfile(profile string) error {
// Same profile validation as create request
return nil
}
// ToJSON converts struct to JSON string
func (r *` + data.Name + `UpdateRequest) ToJSON() (string, error) {
data, err := json.Marshal(r)
return string(data), err
}`
}
func generateHl7FhirPatchRequestModel(data Hl7FhirHandlerData) string {
return `
// ` + data.Name + ` PATCH Request Structure with HL7 FHIR ` + data.FhirVersion + ` JSON Patch
type ` + data.Name + `PatchRequest struct {
BaseRequest
ID string ` + "`json:\"id\" binding:\"required\" validate:\"required\"`" + `
VersionId string ` + "`json:\"versionId,omitempty\"`" + `
Patches []Hl7FhirJsonPatch ` + "`json:\"patches\" binding:\"required\" validate:\"required,dive\"`" + `
}
type Hl7FhirJsonPatch struct {
Op string ` + "`json:\"op\" binding:\"required\" validate:\"required,oneof=add remove replace move copy test\"`" + `
Path string ` + "`json:\"path\" binding:\"required\" validate:\"required\"`" + `
Value interface{} ` + "`json:\"value,omitempty\"`" + `
From string ` + "`json:\"from,omitempty\"`" + `
}
// ValidateHl7FhirPatch validates the ` + data.Name + `PatchRequest
func (r *` + data.Name + `PatchRequest) ValidateHl7FhirPatch() error {
if r.ID == "" {
return fmt.Errorf("resource ID is required for patch operation")
}
if !isValidHl7FhirID(r.ID) {
return fmt.Errorf("invalid resource ID format")
}
if len(r.Patches) == 0 {
return fmt.Errorf("at least one patch operation is required")
}
// Validate each patch operation
for i, patch := range r.Patches {
if patch.Path == "" {
return fmt.Errorf("patch[%d]: path is required", i)
}
// Validate path format (JSON Pointer)
if !strings.HasPrefix(patch.Path, "/") {
return fmt.Errorf("patch[%d]: path must be a valid JSON Pointer", i)
}
if patch.Op == "move" || patch.Op == "copy" {
if patch.From == "" {
return fmt.Errorf("patch[%d]: from is required for %s operation", i, patch.Op)
}
if !strings.HasPrefix(patch.From, "/") {
return fmt.Errorf("patch[%d]: from must be a valid JSON Pointer", i)
}
}
if patch.Op != "remove" && patch.Op != "test" && patch.Value == nil {
return fmt.Errorf("patch[%d]: value is required for %s operation", i, patch.Op)
}
}
return nil
}
// ToJSON converts struct to JSON string
func (r *` + data.Name + `PatchRequest) ToJSON() (string, error) {
data, err := json.Marshal(r)
return string(data), err
}`
}
func generateHl7FhirCommonDataTypes(data Hl7FhirHandlerData) string {
return `
// ============================================================================
// Common HL7 FHIR Data Types for ` + data.FhirVersion + `
// These are reusable data types used across multiple FHIR resources
// Generated for: ` + data.FhirResource + ` | Path: ` + data.Category + `
// ============================================================================
// Narrative - Human-readable summary of the resource
type Hl7FhirNarrative struct {
Status string ` + "`json:\"status\" validate:\"required,oneof=generated extensions additional empty\"`" + `
Div string ` + "`json:\"div\" validate:\"required\"`" + ` // Limited XHTML content
}
// Extension - Additional content defined by implementations
type Hl7FhirExtension struct {
URL string ` + "`json:\"url\" validate:\"required,url\"`" + `
ValueBase64Binary *string ` + "`json:\"valueBase64Binary,omitempty\"`" + `
ValueBoolean *bool ` + "`json:\"valueBoolean,omitempty\"`" + `
ValueCanonical *string ` + "`json:\"valueCanonical,omitempty\" validate:\"omitempty,url\"`" + `
ValueCode *string ` + "`json:\"valueCode,omitempty\"`" + `
ValueDate *string ` + "`json:\"valueDate,omitempty\" validate:\"omitempty,datetime=2006-01-02\"`" + `
ValueDateTime *string ` + "`json:\"valueDateTime,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + `
ValueDecimal *float64 ` + "`json:\"valueDecimal,omitempty\"`" + `
ValueId *string ` + "`json:\"valueId,omitempty\"`" + `
ValueInstant *string ` + "`json:\"valueInstant,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + `
ValueInteger *int ` + "`json:\"valueInteger,omitempty\"`" + `
ValueMarkdown *string ` + "`json:\"valueMarkdown,omitempty\"`" + `
ValueOid *string ` + "`json:\"valueOid,omitempty\"`" + `
ValuePositiveInt *int ` + "`json:\"valuePositiveInt,omitempty\" validate:\"omitempty,min=1\"`" + `
ValueString *string ` + "`json:\"valueString,omitempty\"`" + `
ValueTime *string ` + "`json:\"valueTime,omitempty\" validate:\"omitempty,datetime=15:04:05\"`" + `
ValueUnsignedInt *int ` + "`json:\"valueUnsignedInt,omitempty\" validate:\"omitempty,min=0\"`" + `
ValueUri *string ` + "`json:\"valueUri,omitempty\" validate:\"omitempty,url\"`" + `
ValueUrl *string ` + "`json:\"valueUrl,omitempty\" validate:\"omitempty,url\"`" + `
ValueUuid *string ` + "`json:\"valueUuid,omitempty\" validate:\"omitempty,uuid\"`" + `
// Complex data types
ValueAddress *Hl7FhirAddress ` + "`json:\"valueAddress,omitempty\"`" + `
ValueAge *Hl7FhirAge ` + "`json:\"valueAge,omitempty\"`" + `
ValueAnnotation *Hl7FhirAnnotation ` + "`json:\"valueAnnotation,omitempty\"`" + `
ValueAttachment *Hl7FhirAttachment ` + "`json:\"valueAttachment,omitempty\"`" + `
ValueCodeableConcept *Hl7FhirCodeableConcept ` + "`json:\"valueCodeableConcept,omitempty\"`" + `
ValueCoding *Hl7FhirCoding ` + "`json:\"valueCoding,omitempty\"`" + `
ValueContactPoint *Hl7FhirContactPoint ` + "`json:\"valueContactPoint,omitempty\"`" + `
ValueCount *Hl7FhirCount ` + "`json:\"valueCount,omitempty\"`" + `
ValueDistance *Hl7FhirDistance ` + "`json:\"valueDistance,omitempty\"`" + `
ValueDuration *Hl7FhirDuration ` + "`json:\"valueDuration,omitempty\"`" + `
ValueHumanName *Hl7FhirHumanName ` + "`json:\"valueHumanName,omitempty\"`" + `
ValueIdentifier *Hl7FhirIdentifier ` + "`json:\"valueIdentifier,omitempty\"`" + `
ValueMoney *Hl7FhirMoney ` + "`json:\"valueMoney,omitempty\"`" + `
ValuePeriod *Hl7FhirPeriod ` + "`json:\"valuePeriod,omitempty\"`" + `
ValueQuantity *Hl7FhirQuantity ` + "`json:\"valueQuantity,omitempty\"`" + `
ValueRange *Hl7FhirRange ` + "`json:\"valueRange,omitempty\"`" + `
ValueRatio *Hl7FhirRatio ` + "`json:\"valueRatio,omitempty\"`" + `
ValueReference *Hl7FhirReference ` + "`json:\"valueReference,omitempty\"`" + `
ValueSampledData *Hl7FhirSampledData ` + "`json:\"valueSampledData,omitempty\"`" + `
ValueSignature *Hl7FhirSignature ` + "`json:\"valueSignature,omitempty\"`" + `
ValueTiming *Hl7FhirTiming ` + "`json:\"valueTiming,omitempty\"`" + `
ValueContactDetail *Hl7FhirContactDetail ` + "`json:\"valueContactDetail,omitempty\"`" + `
ValueContributor *Hl7FhirContributor ` + "`json:\"valueContributor,omitempty\"`" + `
ValueDataRequirement *Hl7FhirDataRequirement ` + "`json:\"valueDataRequirement,omitempty\"`" + `
ValueExpression *Hl7FhirExpression ` + "`json:\"valueExpression,omitempty\"`" + `
ValueParameterDefinition *Hl7FhirParameterDefinition ` + "`json:\"valueParameterDefinition,omitempty\"`" + `
ValueRelatedArtifact *Hl7FhirRelatedArtifact ` + "`json:\"valueRelatedArtifact,omitempty\"`" + `
ValueTriggerDefinition *Hl7FhirTriggerDefinition ` + "`json:\"valueTriggerDefinition,omitempty\"`" + `
ValueUsageContext *Hl7FhirUsageContext ` + "`json:\"valueUsageContext,omitempty\"`" + `
ValueDosage *Hl7FhirDosage ` + "`json:\"valueDosage,omitempty\"`" + `
}
// Coding - Reference to a code defined by a terminology system
type Hl7FhirCoding struct {
System string ` + "`json:\"system,omitempty\" validate:\"omitempty,url\"`" + `
Version string ` + "`json:\"version,omitempty\"`" + `
Code string ` + "`json:\"code,omitempty\"`" + `
Display string ` + "`json:\"display,omitempty\"`" + `
UserSelected *bool ` + "`json:\"userSelected,omitempty\"`" + `
}
// CodeableConcept - Concept defined by Coding(s) and/or text
type Hl7FhirCodeableConcept struct {
Coding []Hl7FhirCoding ` + "`json:\"coding,omitempty\" validate:\"dive\"`" + `
Text string ` + "`json:\"text,omitempty\"`" + `
}
// Reference - Reference to another resource
type Hl7FhirReference struct {
Reference string ` + "`json:\"reference,omitempty\"`" + `
Type string ` + "`json:\"type,omitempty\"`" + `
Identifier Hl7FhirIdentifier ` + "`json:\"identifier,omitempty\"`" + `
Display string ` + "`json:\"display,omitempty\"`" + `
}
// Identifier - Identifier for a resource
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\"`" + `
}
// Period - Time range defined by start and end date/time
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\"`" + `
}
// Quantity - Measured amount (or range of measured amounts)
type Hl7FhirQuantity struct {
Value float64 ` + "`json:\"value,omitempty\"`" + `
Comparator string ` + "`json:\"comparator,omitempty\" validate:\"omitempty,oneof=< <= >= > ad\"`" + `
Unit string ` + "`json:\"unit,omitempty\"`" + `
System string ` + "`json:\"system,omitempty\" validate:\"omitempty,url\"`" + `
Code string ` + "`json:\"code,omitempty\"`" + `
}
// Range - Set of values bounded by low and high
type Hl7FhirRange struct {
Low Hl7FhirQuantity ` + "`json:\"low,omitempty\"`" + `
High Hl7FhirQuantity ` + "`json:\"high,omitempty\"`" + `
}
// Ratio - Relationship between two quantities
type Hl7FhirRatio struct {
Numerator Hl7FhirQuantity ` + "`json:\"numerator,omitempty\"`" + `
Denominator Hl7FhirQuantity ` + "`json:\"denominator,omitempty\"`" + `
}
// SampledData - Data that comes from observations
type Hl7FhirSampledData struct {
Origin Hl7FhirQuantity ` + "`json:\"origin\" validate:\"required\"`" + `
Period float64 ` + "`json:\"period\" validate:\"required,min=0\"`" + `
Factor float64 ` + "`json:\"factor,omitempty\"`" + `
LowerLimit float64 ` + "`json:\"lowerLimit,omitempty\"`" + `
UpperLimit float64 ` + "`json:\"upperLimit,omitempty\"`" + `
Dimensions int ` + "`json:\"dimensions\" validate:\"required,min=1\"`" + `
Data string ` + "`json:\"data,omitempty\"`" + `
}
// Attachment - Content in a format defined elsewhere
type Hl7FhirAttachment struct {
ContentType string ` + "`json:\"contentType,omitempty\"`" + `
Language string ` + "`json:\"language,omitempty\" validate:\"omitempty,len=2\"`" + `
Data string ` + "`json:\"data,omitempty\"`" + `
Url string ` + "`json:\"url,omitempty\" validate:\"omitempty,url\"`" + `
Size int ` + "`json:\"size,omitempty\" validate:\"omitempty,min=0\"`" + `
Hash string ` + "`json:\"hash,omitempty\"`" + `
Title string ` + "`json:\"title,omitempty\"`" + `
Creation string ` + "`json:\"creation,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + `
Height int ` + "`json:\"height,omitempty\" validate:\"omitempty,min=1\"`" + `
Width int ` + "`json:\"width,omitempty\" validate:\"omitempty,min=1\"`" + `
Frames int ` + "`json:\"frames,omitempty\" validate:\"omitempty,min=1\"`" + `
Duration float64` + "`json:\"duration,omitempty\" validate:\"omitempty,min=0\"`" + `
Pages int ` + "`json:\"pages,omitempty\" validate:\"omitempty,min=1\"`" + `
}
// ContactPoint - Details for contacting
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\"`" + `
}
// HumanName - Name of a human or other living entity
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\"`" + `
}
// Address - Postal address
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\"`" + `
}
// Age - Duration with context
type Hl7FhirAge struct {
Value float64 ` + "`json:\"value,omitempty\" validate:\"omitempty,min=0\"`" + `
Comparator string ` + "`json:\"comparator,omitempty\" validate:\"omitempty,oneof=< <= >= >\"`" + `
Unit string ` + "`json:\"unit,omitempty\"`" + `
System string ` + "`json:\"system,omitempty\" validate:\"omitempty,url\"`" + `
Code string ` + "`json:\"code,omitempty\"`" + `
}
// Count - Integer with units
type Hl7FhirCount struct {
Value int ` + "`json:\"value,omitempty\" validate:\"omitempty,min=0\"`" + `
Comparator string ` + "`json:\"comparator,omitempty\" validate:\"omitempty,oneof=< <= >= >\"`" + `
Unit string ` + "`json:\"unit,omitempty\"`" + `
System string ` + "`json:\"system,omitempty\" validate:\"omitempty,url\"`" + `
Code string ` + "`json:\"code,omitempty\"`" + `
}
// Distance - Length with units
type Hl7FhirDistance struct {
Value float64 ` + "`json:\"value,omitempty\" validate:\"omitempty,min=0\"`" + `
Comparator string ` + "`json:\"comparator,omitempty\" validate:\"omitempty,oneof=< <= >= >\"`" + `
Unit string ` + "`json:\"unit,omitempty\"`" + `
System string ` + "`json:\"system,omitempty\" validate:\"omitempty,url\"`" + `
Code string ` + "`json:\"code,omitempty\"`" + `
}
// Duration - Length of time
type Hl7FhirDuration struct {
Value float64 ` + "`json:\"value,omitempty\" validate:\"omitempty,min=0\"`" + `
Comparator string ` + "`json:\"comparator,omitempty\" validate:\"omitempty,oneof=< <= >= >\"`" + `
Unit string ` + "`json:\"unit,omitempty\"`" + `
System string ` + "`json:\"system,omitempty\" validate:\"omitempty,url\"`" + `
Code string ` + "`json:\"code,omitempty\"`" + `
}
// Money - Amount of economic utility
type Hl7FhirMoney struct {
Value float64 ` + "`json:\"value,omitempty\" validate:\"omitempty,min=0\"`" + `
Currency string ` + "`json:\"currency,omitempty\" validate:\"omitempty,len=3\"`" + `
}
// Annotation - Text node with attribution
type Hl7FhirAnnotation struct {
AuthorReference Hl7FhirReference ` + "`json:\"authorReference,omitempty\"`" + `
AuthorString string ` + "`json:\"authorString,omitempty\"`" + `
Time string ` + "`json:\"time,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + `
Text string ` + "`json:\"text\" validate:\"required\"`" + `
}
// Timing - When something happens
type Hl7FhirTiming struct {
Event []string ` + "`json:\"event,omitempty\"`" + `
Repeat Hl7FhirTimingRepeat ` + "`json:\"repeat,omitempty\"`" + `
Code Hl7FhirCodeableConcept` + "`json:\"code,omitempty\"`" + `
}
// TimingRepeat - When events repeat
type Hl7FhirTimingRepeat struct {
BoundsDuration Hl7FhirDuration ` + "`json:\"boundsDuration,omitempty\"`" + `
BoundsRange Hl7FhirRange ` + "`json:\"boundsRange,omitempty\"`" + `
BoundsPeriod Hl7FhirPeriod ` + "`json:\"boundsPeriod,omitempty\"`" + `
Count int ` + "`json:\"count,omitempty\" validate:\"omitempty,min=0\"`" + `
CountMax int ` + "`json:\"countMax,omitempty\" validate:\"omitempty,min=0\"`" + `
Duration float64 ` + "`json:\"duration,omitempty\" validate:\"omitempty,min=0\"`" + `
DurationMax float64 ` + "`json:\"durationMax,omitempty\" validate:\"omitempty,min=0\"`" + `
DurationUnit string ` + "`json:\"durationUnit,omitempty\" validate:\"omitempty,oneof=s min h d wk mo a\"`" + `
Frequency int ` + "`json:\"frequency,omitempty\" validate:\"omitempty,min=1\"`" + `
FrequencyMax int ` + "`json:\"frequencyMax,omitempty\" validate:\"omitempty,min=1\"`" + `
Period float64 ` + "`json:\"period,omitempty\" validate:\"omitempty,min=0\"`" + `
PeriodMax float64 ` + "`json:\"periodMax,omitempty\" validate:\"omitempty,min=0\"`" + `
PeriodUnit string ` + "`json:\"periodUnit,omitempty\" validate:\"omitempty,oneof=s min h d wk mo a\"`" + `
DayOfWeek []string ` + "`json:\"dayOfWeek,omitempty\"`" + `
TimeOfDay []string ` + "`json:\"timeOfDay,omitempty\"`" + `
When []string ` + "`json:\"when,omitempty\"`" + `
Offset int ` + "`json:\"offset,omitempty\" validate:\"omitempty,min=0\"`" + `
}
// ContactDetail - Contact details (See also ContactPoint)
type Hl7FhirContactDetail struct {
Name string ` + "`json:\"name,omitempty\"`" + `
Telecom []Hl7FhirContactPoint ` + "`json:\"telecom,omitempty\" validate:\"dive\"`" + `
}
// Contributor - Contributor information
type Hl7FhirContributor struct {
Type string ` + "`json:\"type\" validate:\"required,oneof=author editor reviewer endorser\"`" + `
Name string ` + "`json:\"name\" validate:\"required\"`" + `
Contact []Hl7FhirContactDetail ` + "`json:\"contact,omitempty\" validate:\"dive\"`" + `
}
// DataRequirement - Describes a required data item
type Hl7FhirDataRequirement struct {
Type string ` + "`json:\"type\" validate:\"required\"`" + `
Profile []string ` + "`json:\"profile,omitempty\"`" + `
SubjectCodeableConcept Hl7FhirCodeableConcept ` + "`json:\"subjectCodeableConcept,omitempty\"`" + `
SubjectReference Hl7FhirReference ` + "`json:\"subjectReference,omitempty\"`" + `
MustSupport []string ` + "`json:\"mustSupport,omitempty\"`" + `
CodeFilter []Hl7FhirDataRequirementCodeFilter ` + "`json:\"codeFilter,omitempty\"`" + `
DateFilter []Hl7FhirDataRequirementDateFilter ` + "`json:\"dateFilter,omitempty\"`" + `
Limit int ` + "`json:\"limit,omitempty\" validate:\"omitempty,min=1\"`" + `
Sort []Hl7FhirDataRequirementSort ` + "`json:\"sort,omitempty\"`" + `
}
// DataRequirementCodeFilter - Code filters specify additional constraints
type Hl7FhirDataRequirementCodeFilter struct {
Path string ` + "`json:\"path,omitempty\"`" + `
SearchParam string ` + "`json:\"searchParam,omitempty\"`" + `
ValueSet string ` + "`json:\"valueSet,omitempty\" validate:\"omitempty,url\"`" + `
Code []Hl7FhirCoding ` + "`json:\"code,omitempty\" validate:\"dive\"`" + `
}
// DataRequirementDateFilter - Date filters specify additional constraints
type Hl7FhirDataRequirementDateFilter struct {
Path string ` + "`json:\"path,omitempty\"`" + `
SearchParam string ` + "`json:\"searchParam,omitempty\"`" + `
ValueDateTime string ` + "`json:\"valueDateTime,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + `
ValuePeriod Hl7FhirPeriod ` + "`json:\"valuePeriod,omitempty\"`" + `
ValueDuration Hl7FhirDuration ` + "`json:\"valueDuration,omitempty\"`" + `
}
// DataRequirementSort - Specifies the order of the results
type Hl7FhirDataRequirementSort struct {
Path string ` + "`json:\"path\" validate:\"required\"`" + `
Direction string ` + "`json:\"direction\" validate:\"required,oneof=ascending descending\"`" + `
}
// Expression - Expression language
type Hl7FhirExpression struct {
Description string ` + "`json:\"description,omitempty\"`" + `
Name string ` + "`json:\"name,omitempty\"`" + `
Language string ` + "`json:\"language\" validate:\"required\"`" + `
Expression string ` + "`json:\"expression,omitempty\"`" + `
Reference string ` + "`json:\"reference,omitempty\" validate:\"omitempty,url\"`" + `
}
// ParameterDefinition - Definition of a parameter to a module
type Hl7FhirParameterDefinition struct {
Name string ` + "`json:\"name,omitempty\"`" + `
Use string ` + "`json:\"use\" validate:\"required,oneof=in out\"`" + `
Min int ` + "`json:\"min,omitempty\" validate:\"omitempty,min=0\"`" + `
Max string ` + "`json:\"max,omitempty\"`" + `
Documentation string ` + "`json:\"documentation,omitempty\"`" + `
Type string ` + "`json:\"type\" validate:\"required\"`" + `
Profile string ` + "`json:\"profile,omitempty\" validate:\"omitempty,url\"`" + `
}
// RelatedArtifact - Related artifacts such as additional documentation
type Hl7FhirRelatedArtifact struct {
Type string ` + "`json:\"type\" validate:\"required,oneof=documentation justification citation predecessor successor derived-from depends-on composed-of\"`" + `
Label string ` + "`json:\"label,omitempty\"`" + `
Display string ` + "`json:\"display,omitempty\"`" + `
Citation string ` + "`json:\"citation,omitempty\"`" + `
Url string ` + "`json:\"url,omitempty\" validate:\"omitempty,url\"`" + `
Document Hl7FhirAttachment ` + "`json:\"document,omitempty\"`" + `
Resource string ` + "`json:\"resource,omitempty\" validate:\"omitempty,url\"`" + `
}
// TriggerDefinition - Defines an expected trigger for a module
type Hl7FhirTriggerDefinition struct {
Type string ` + "`json:\"type\" validate:\"required,oneof=named-event periodic data-changed data-added data-modified data-removed data-accessed data-access-ended\"`" + `
Name string ` + "`json:\"name,omitempty\"`" + `
TimingTiming Hl7FhirTiming ` + "`json:\"timingTiming,omitempty\"`" + `
TimingReference Hl7FhirReference ` + "`json:\"timingReference,omitempty\"`" + `
TimingDate string ` + "`json:\"timingDate,omitempty\" validate:\"omitempty,datetime=2006-01-02\"`" + `
TimingDateTime string ` + "`json:\"timingDateTime,omitempty\" validate:\"omitempty,datetime=2006-01-02T15:04:05Z07:00\"`" + `
Data []Hl7FhirDataRequirement ` + "`json:\"data,omitempty\" validate:\"dive\"`" + `
Condition Hl7FhirExpression ` + "`json:\"condition,omitempty\"`" + `
}
// UsageContext - Describes the context of use for a conformance or knowledge resource
type Hl7FhirUsageContext struct {
Code Hl7FhirCoding ` + "`json:\"code\" validate:\"required\"`" + `
ValueCodeableConcept Hl7FhirCodeableConcept ` + "`json:\"valueCodeableConcept,omitempty\"`" + `
ValueQuantity Hl7FhirQuantity ` + "`json:\"valueQuantity,omitempty\"`" + `
ValueRange Hl7FhirRange ` + "`json:\"valueRange,omitempty\"`" + `
ValueReference Hl7FhirReference ` + "`json:\"valueReference,omitempty\"`" + `
}
// Dosage - How medication is/was taken or should be taken
type Hl7FhirDosage struct {
Sequence int ` + "`json:\"sequence,omitempty\" validate:\"omitempty,min=1\"`" + `
Text string ` + "`json:\"text,omitempty\"`" + `
AdditionalInstruction []Hl7FhirCodeableConcept ` + "`json:\"additionalInstruction,omitempty\" validate:\"dive\"`" + `
PatientInstruction string ` + "`json:\"patientInstruction,omitempty\"`" + `
Timing Hl7FhirTiming ` + "`json:\"timing,omitempty\"`" + `
AsNeededBoolean *bool ` + "`json:\"asNeededBoolean,omitempty\"`" + `
AsNeededCodeableConcept Hl7FhirCodeableConcept ` + "`json:\"asNeededCodeableConcept,omitempty\"`" + `
Site Hl7FhirCodeableConcept ` + "`json:\"site,omitempty\"`" + `
Route Hl7FhirCodeableConcept ` + "`json:\"route,omitempty\"`" + `
Method Hl7FhirCodeableConcept ` + "`json:\"method,omitempty\"`" + `
DoseAndRate []Hl7FhirDosageDoseAndRate ` + "`json:\"doseAndRate,omitempty\" validate:\"dive\"`" + `
MaxDosePerPeriod []Hl7FhirRatio ` + "`json:\"maxDosePerPeriod,omitempty\" validate:\"dive\"`" + `
MaxDosePerAdministration Hl7FhirQuantity ` + "`json:\"maxDosePerAdministration,omitempty\"`" + `
MaxDosePerLifetime Hl7FhirQuantity ` + "`json:\"maxDosePerLifetime,omitempty\"`" + `
}
// DosageDoseAndRate - Amount of medication administered
type Hl7FhirDosageDoseAndRate struct {
Type Hl7FhirCodeableConcept ` + "`json:\"type,omitempty\"`" + `
DoseRange Hl7FhirRange ` + "`json:\"doseRange,omitempty\"`" + `
DoseQuantity Hl7FhirQuantity ` + "`json:\"doseQuantity,omitempty\"`" + `
RateRatio Hl7FhirRatio ` + "`json:\"rateRatio,omitempty\"`" + `
RateRange Hl7FhirRange ` + "`json:\"rateRange,omitempty\"`" + `
RateQuantity Hl7FhirQuantity ` + "`json:\"rateQuantity,omitempty\"`" + `
}
// ============================================================================
// End of Common HL7 FHIR Data Types
// ============================================================================
`
}
// Continue with additional methods and model generation...
func writeFile(filename, content string) {
if err := os.WriteFile(filename, []byte(content), 0644); err != nil {
fmt.Printf("❌ Error creating file %s: %v\n", filename, err)
return
}
fmt.Printf("✅ Generated HL7 FHIR file: %s\n", filename)
}