lang/php/lib/Schema/AvroRecordSchema.php (121 lines of code) (raw):

<?php /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Apache\Avro\Schema; /** * @package Avro */ class AvroRecordSchema extends AvroNamedSchema { /** * @var AvroNamedSchema[] array of AvroNamedSchema field definitions of * this AvroRecordSchema */ private $fields; /** * @var array map of field names to field objects. * @internal Not called directly. Memoization of AvroRecordSchema->fieldsHash() */ private $fieldsHash; /** * @param AvroName $name * @param string $namespace * @param string $doc * @param array $fields * @param AvroNamedSchemata &$schemata * @param string $schema_type schema type name * @throws AvroSchemaParseException */ public function __construct( $name, $doc, $fields, &$schemata = null, $schema_type = AvroSchema::RECORD_SCHEMA, $aliases = null ) { if (is_null($fields)) { throw new AvroSchemaParseException( 'Record schema requires a non-empty fields attribute' ); } if (AvroSchema::REQUEST_SCHEMA == $schema_type) { parent::__construct($schema_type, $name); } else { parent::__construct($schema_type, $name, $doc, $schemata, $aliases); } [$x, $namespace] = $name->nameAndNamespace(); $this->fields = self::parseFields($fields, $namespace, $schemata); } /** * @param mixed $field_data * @param string $default_namespace namespace of enclosing schema * @param AvroNamedSchemata &$schemata * @returns AvroField[] * @throws AvroSchemaParseException */ public static function parseFields($field_data, $default_namespace, &$schemata) { $fields = array(); $field_names = array(); $alias_names = []; foreach ($field_data as $index => $field) { $name = $field[AvroField::FIELD_NAME_ATTR] ?? null; $type = $field[AvroSchema::TYPE_ATTR] ?? null; $order = $field[AvroField::ORDER_ATTR] ?? null; $aliases = $field[AvroField::ALIASES_ATTR] ?? null; $default = null; $has_default = false; if (array_key_exists(AvroField::DEFAULT_ATTR, $field)) { $default = $field[AvroField::DEFAULT_ATTR]; $has_default = true; } if (in_array($name, $field_names)) { throw new AvroSchemaParseException( sprintf("Field name %s is already in use", $name) ); } $is_schema_from_schemata = false; $field_schema = null; if ( is_string($type) && $field_schema = $schemata->schemaByName( new AvroName($type, null, $default_namespace) ) ) { $is_schema_from_schemata = true; } else { $field_schema = self::subparse($type, $default_namespace, $schemata); } $new_field = new AvroField( $name, $field_schema, $is_schema_from_schemata, $has_default, $default, $order, $aliases ); $field_names[] = $name; if ($new_field->hasAliases() && array_intersect($alias_names, $new_field->getAliases())) { throw new AvroSchemaParseException("Alias already in use"); } if ($new_field->hasAliases()) { array_push($alias_names, ...$new_field->getAliases()); } $fields[] = $new_field; } return $fields; } /** * @returns mixed */ public function toAvro() { $avro = parent::toAvro(); $fields_avro = array(); foreach ($this->fields as $field) { $fields_avro[] = $field->toAvro(); } if (AvroSchema::REQUEST_SCHEMA === $this->type) { return $fields_avro; } $avro[AvroSchema::FIELDS_ATTR] = $fields_avro; return $avro; } /** * @returns array the schema definitions of the fields of this AvroRecordSchema */ public function fields() { return $this->fields; } /** * @returns array a hash table of the fields of this AvroRecordSchema fields * keyed by each field's name */ public function fieldsHash() { if (is_null($this->fieldsHash)) { $hash = array(); foreach ($this->fields as $field) { $hash[$field->name()] = $field; } $this->fieldsHash = $hash; } return $this->fieldsHash; } public function fieldsByAlias() { $hash = []; foreach ($this->fields as $field) { if ($field->hasAliases()) { foreach ($field->getAliases() as $a) { $hash[$a] = $field; } } } return $hash; } }