| 177 | } |
| 178 | |
| 179 | func getFirstSemanticTypeInPath(ast *parserbase.PathAST, objectSchema *storepb.ObjectSchema) string { |
| 180 | if ast == nil || ast.Root == nil || objectSchema == nil { |
| 181 | return "" |
| 182 | } |
| 183 | |
| 184 | // Skip the first node because it always represents the container. |
| 185 | astWoutContainer := parserbase.NewPathAST(ast.Root.GetNext()) |
| 186 | if astWoutContainer == nil || astWoutContainer.Root == nil { |
| 187 | return "" |
| 188 | } |
| 189 | |
| 190 | if objectSchema.SemanticType != "" { |
| 191 | return objectSchema.SemanticType |
| 192 | } |
| 193 | |
| 194 | os := objectSchema |
| 195 | |
| 196 | for node := astWoutContainer.Root; node != nil; node = node.GetNext() { |
| 197 | if node.GetIdentifier() == "" { |
| 198 | return "" |
| 199 | } |
| 200 | |
| 201 | switch node := node.(type) { |
| 202 | case *parserbase.ItemSelector: |
| 203 | if os.Type != storepb.ObjectSchema_OBJECT { |
| 204 | return "" |
| 205 | } |
| 206 | var valid bool |
| 207 | if v := os.GetStructKind().GetProperties(); v != nil { |
| 208 | if child, ok := v[node.GetIdentifier()]; ok { |
| 209 | os = child |
| 210 | valid = true |
| 211 | } |
| 212 | } |
| 213 | if !valid { |
| 214 | return "" |
| 215 | } |
| 216 | case *parserbase.ArraySelector: |
| 217 | if os.Type != storepb.ObjectSchema_OBJECT { |
| 218 | return "" |
| 219 | } |
| 220 | var valid bool |
| 221 | if v := os.GetStructKind().GetProperties(); v != nil { |
| 222 | if child, ok := v[node.GetIdentifier()]; ok { |
| 223 | os = child |
| 224 | valid = true |
| 225 | } |
| 226 | } |
| 227 | if !valid { |
| 228 | return "" |
| 229 | } |
| 230 | |
| 231 | if os.Type != storepb.ObjectSchema_ARRAY { |
| 232 | return "" |
| 233 | } |
| 234 | |
| 235 | os = os.GetArrayKind().GetKind() |
| 236 | if os == nil { |