001package gudusoft.gsqlparser.catalog.input.model; 002 003import gudusoft.gsqlparser.catalog.runtime.CatalogObjectKind; 004 005import java.util.ArrayList; 006import java.util.Collections; 007import java.util.EnumSet; 008import java.util.List; 009import java.util.Objects; 010import java.util.Set; 011 012/** 013 * Routine entry (function, procedure, or package) inside a {@link SchemaModel}. 014 * 015 * <p>Plan ยง6. {@link #kind()} is restricted to one of 016 * {@link CatalogObjectKind#FUNCTION FUNCTION}, 017 * {@link CatalogObjectKind#PROCEDURE PROCEDURE}, 018 * {@link CatalogObjectKind#PACKAGE PACKAGE}, or 019 * {@link CatalogObjectKind#ROUTINE ROUTINE}; other kinds belong on different 020 * model types.</p> 021 */ 022public final class RoutineModel { 023 024 private static final Set<CatalogObjectKind> ALLOWED_KINDS = EnumSet.of( 025 CatalogObjectKind.FUNCTION, 026 CatalogObjectKind.PROCEDURE, 027 CatalogObjectKind.PACKAGE, 028 CatalogObjectKind.ROUTINE); 029 030 private final String name; 031 private final CatalogObjectKind kind; 032 private final String returns; 033 private final List<ColumnModel> parameters; 034 035 private RoutineModel(Builder b) { 036 if (b.name == null || b.name.isEmpty()) { 037 throw new IllegalArgumentException("RoutineModel.name is required"); 038 } 039 if (b.kind == null) { 040 throw new IllegalArgumentException( 041 "RoutineModel.kind is required (routine '" + b.name + "')"); 042 } 043 if (!ALLOWED_KINDS.contains(b.kind)) { 044 throw new IllegalArgumentException( 045 "RoutineModel.kind must be one of FUNCTION/PROCEDURE/PACKAGE/ROUTINE; got " + b.kind); 046 } 047 this.name = b.name; 048 this.kind = b.kind; 049 this.returns = b.returns; 050 this.parameters = Collections.unmodifiableList(new ArrayList<ColumnModel>(b.parameters)); 051 } 052 053 public static Builder builder() { 054 return new Builder(); 055 } 056 057 public String name() { 058 return name; 059 } 060 061 public CatalogObjectKind kind() { 062 return kind; 063 } 064 065 /** Return-type string for FUNCTION routines; {@code null} for PROCEDURE / PACKAGE. */ 066 public String returns() { 067 return returns; 068 } 069 070 public List<ColumnModel> parameters() { 071 return parameters; 072 } 073 074 @Override 075 public boolean equals(Object o) { 076 if (this == o) return true; 077 if (!(o instanceof RoutineModel)) return false; 078 RoutineModel that = (RoutineModel) o; 079 return name.equals(that.name) 080 && kind == that.kind 081 && Objects.equals(returns, that.returns) 082 && parameters.equals(that.parameters); 083 } 084 085 @Override 086 public int hashCode() { 087 return Objects.hash(name, kind, returns, parameters); 088 } 089 090 @Override 091 public String toString() { 092 return "RoutineModel{name=" + name 093 + ", kind=" + kind 094 + ", returns=" + returns 095 + ", params=" + parameters.size() + '}'; 096 } 097 098 public static final class Builder { 099 100 private String name; 101 private CatalogObjectKind kind; 102 private String returns; 103 private final List<ColumnModel> parameters = new ArrayList<ColumnModel>(); 104 105 private Builder() { 106 } 107 108 public Builder name(String v) { 109 this.name = v; 110 return this; 111 } 112 113 public Builder kind(CatalogObjectKind v) { 114 this.kind = v; 115 return this; 116 } 117 118 public Builder returns(String v) { 119 this.returns = v; 120 return this; 121 } 122 123 public Builder addParameter(ColumnModel v) { 124 if (v == null) { 125 throw new IllegalArgumentException("RoutineModel parameter may not be null"); 126 } 127 this.parameters.add(v); 128 return this; 129 } 130 131 public RoutineModel build() { 132 return new RoutineModel(this); 133 } 134 } 135}