public function translate(SpecificationInterface $specification) : string
 {
     switch (true) {
         case $specification instanceof ComparatorInterface:
             if ($specification->sign() !== '==') {
                 throw new OnlyEqualityCanBeTranslatedException();
             }
             return sprintf('%s=%s', $specification->property(), $specification->value());
         case $specification instanceof CompositeInterface:
             if ((string) $specification->operator() === Operator::OR) {
                 throw new OnlyAndCompositionCanBeTranslatedException();
             }
             return sprintf('%s&%s', $this->translate($specification->left()), $this->translate($specification->right()));
         default:
             throw new SpecificationCantBeTranslatedException();
     }
 }
 private function extract(SpecificationInterface $specification) : array
 {
     $data = [];
     switch (true) {
         case $specification instanceof ComparatorInterface:
             $data[$specification->property()] = $specification->value();
             break;
         case $specification instanceof CompositeInterface:
             if ((string) $specification->operator() === Operator::OR) {
                 throw new SpecificationNotUsableAsQueryException();
             }
             $data = array_merge($data, $this->extract($specification->left()), $this->extract($specification->right()));
             break;
         default:
             throw new SpecificationNotUsableAsQueryException();
     }
     return $data;
 }