/**
  * @return array
  */
 protected function getEmbeddedCommands(EmbeddedEntityListAttribute $attribute, array $values, EntityInterface $parent_entity = null)
 {
     $errors = [];
     $affected_identifiers = [];
     $attribute_name = $attribute->getName();
     $embedded_entity_list = $parent_entity ? $parent_entity->getValue($attribute_name) : new EntityList();
     $builder_list = new CommandBuilderList();
     foreach ($values as $position => $embedded_values) {
         if (!isset($embedded_values['@type'])) {
             $value_path = sprintf('%s.%d.@type', $attribute_name, $position);
             $errors[$value_path]['@incidents'][] = ['path' => $attribute->getPath(), 'incidents' => ['invalid_type' => ['reason' => 'missing']]];
             continue;
         }
         $embed_type_prefix = $embedded_values['@type'];
         unset($embedded_values['@type']);
         $embed_type = $attribute->getEmbeddedTypeByPrefix($embed_type_prefix);
         if (!$embed_type) {
             $value_path = sprintf('%s.%d.@type', $attribute_name, $position);
             $errors[$value_path]['@incidents'][] = ['path' => $attribute->getPath(), 'incidents' => ['invalid_type' => ['reason' => 'unknown']]];
             continue;
         }
         /*
          * Filter entities from the entity by incoming payload identifiers. If the
          * identifier is not matched then prepare an 'add' command, otherwise a 'modify'.
          */
         $affected_entity = $embedded_entity_list->filter(function ($embedded_entity) use($embedded_values) {
             return $embedded_entity instanceof EntityInterface && isset($embedded_values['identifier']) && $embedded_entity->getIdentifier() === $embedded_values['identifier'];
         })->getFirst();
         if (!$affected_entity) {
             $builder_list->push((new self($embed_type, AddEmbeddedEntityCommand::CLASS))->withParentAttributeName($attribute_name)->withPosition($position)->withValues($embedded_values));
         } else {
             $affected_identifiers[] = $affected_entity->getIdentifier();
             $modified_values = $this->filterUnmodifiedValues($affected_entity, $embedded_values);
             // prepare a modify command if values or position has changed
             if (!empty($modified_values) || $embedded_entity_list->getKey($affected_entity) != $position) {
                 $builder_list->push((new self($embed_type, ModifyEmbeddedEntityCommand::CLASS))->fromEntity($affected_entity)->withParentAttributeName($attribute_name)->withPosition($position)->withValues($modified_values));
             }
         }
     }
     /*
      * Iterate the attribute entity list and prepare remove commands for
      * any embedded entities with no incoming payload, or compensate for commands
      * which already exist.
      */
     foreach ($embedded_entity_list as $embedded_entity) {
         // if an entity is not found in the payload then we do compensation checks to make
         // sure we don't inadvertently add an existing entity
         if (!in_array($embedded_entity->getIdentifier(), $affected_identifiers)) {
             // look for any add command which has no difference in values for the current entity
             $command_key = null;
             foreach ($builder_list as $key => $command_builder) {
                 if ($command_builder->getCommandClass() === AddEmbeddedEntityCommand::CLASS && empty($this->filterUnmodifiedValues($embedded_entity, $command_builder->getValues()))) {
                     $command_key = $key;
                     break;
                 }
             }
             if (!is_null($command_key)) {
                 // remove the unnecessary add command if the entity already exists in the entity
                 $builder_list->splice($command_key);
             } else {
                 // the entity was not found in the payload so we can prepare removal
                 $builder_list->push((new self($embedded_entity->getType(), RemoveEmbeddedEntityCommand::CLASS))->fromEntity($embedded_entity)->withParentAttributeName($attribute_name));
             }
         }
     }
     $build_result = $builder_list->build();
     if (!empty($errors)) {
         if ($build_result instanceof Error) {
             $errors = array_merge($errors, $build_result->get());
         }
         return Error::unit($errors);
     }
     return $build_result;
 }