/**
  * @param array $fieldData
  * @return Field
  */
 private function getField(array $fieldData)
 {
     $field = new Field();
     $field->setName($fieldData['name']);
     if (isset($fieldData['description'])) {
         $field->setDescription($fieldData['description']);
     }
     if (isset($fieldData['type'])) {
         $field->setType($fieldData['type']);
     }
     if (isset($fieldData['field_type'])) {
         $field->setFieldType($fieldData['field_type']);
     }
     $required = isset($fieldData['required']) ? (bool) $fieldData['required'] : false;
     $field->setRequired($required);
     return $field;
 }
 /**
  * Create documentation details for a given service in a given version of
  * an API module
  *
  * @param string $apiName
  * @param int|string $apiVersion
  * @param string $serviceName
  * @return Service
  */
 public function createService(Api $api, $serviceName)
 {
     $service = new Service();
     $service->setApi($api);
     $serviceData = null;
     $isRest = false;
     $isRpc = false;
     $hasSegments = false;
     $hasFields = false;
     foreach ($this->config['zf-rest'] as $serviceClassName => $restConfig) {
         if (strpos($serviceClassName, $api->getName() . '\\') === 0 && isset($restConfig['service_name']) && $restConfig['service_name'] === $serviceName && strstr($serviceClassName, '\\V' . $api->getVersion() . '\\') !== false) {
             $serviceData = $restConfig;
             $isRest = true;
             $hasSegments = true;
             break;
         }
     }
     if (!$serviceData) {
         foreach ($this->config['zf-rpc'] as $serviceClassName => $rpcConfig) {
             if (strpos($serviceClassName, $api->getName() . '\\') === 0 && isset($rpcConfig['service_name']) && $rpcConfig['service_name'] === $serviceName && strstr($serviceClassName, '\\V' . $api->getVersion() . '\\') !== false) {
                 $serviceData = $rpcConfig;
                 $serviceData['action'] = $this->marshalActionFromRouteConfig($serviceName, $serviceClassName, $rpcConfig);
                 $isRpc = true;
                 break;
             }
         }
     }
     if (!$serviceData || !isset($serviceClassName)) {
         return false;
     }
     $authorizations = $this->getAuthorizations($serviceClassName);
     $docsArray = $this->getDocumentationConfig($api->getName());
     $service->setName($serviceData['service_name']);
     if (isset($docsArray[$serviceClassName]['description'])) {
         $service->setDescription($docsArray[$serviceClassName]['description']);
     }
     $route = $this->config['router']['routes'][$serviceData['route_name']]['options']['route'];
     $service->setRoute(str_replace('[/v:version]', '', $route));
     // remove internal version prefix, hacky
     if ($isRpc) {
         $hasSegments = $this->hasOptionalSegments($route);
     }
     if (isset($serviceData['route_identifier_name'])) {
         $service->setRouteIdentifierName($serviceData['route_identifier_name']);
     }
     if (isset($this->config['zf-content-validation'][$serviceClassName]['input_filter'])) {
         $validatorName = $this->config['zf-content-validation'][$serviceClassName]['input_filter'];
         $fields = array();
         if (isset($this->config['input_filter_specs'][$validatorName])) {
             foreach ($this->config['input_filter_specs'][$validatorName] as $fieldData) {
                 $fields[] = $field = new Field();
                 $field->setName($fieldData['name']);
                 if (isset($fieldData['description'])) {
                     $field->setDescription($fieldData['description']);
                 }
                 $field->setRequired($fieldData['required']);
             }
             $service->setFields($fields);
             $hasFields = true;
         }
     }
     $baseOperationData = isset($serviceData['collection_http_methods']) ? $serviceData['collection_http_methods'] : $serviceData['http_methods'];
     $ops = array();
     foreach ($baseOperationData as $httpMethod) {
         $op = new Operation();
         $op->setHttpMethod($httpMethod);
         if ($isRest) {
             $description = isset($docsArray[$serviceClassName]['collection'][$httpMethod]['description']) ? $docsArray[$serviceClassName]['collection'][$httpMethod]['description'] : '';
             $op->setDescription($description);
             $requestDescription = isset($docsArray[$serviceClassName]['collection'][$httpMethod]['request']) ? $docsArray[$serviceClassName]['collection'][$httpMethod]['request'] : '';
             $op->setRequestDescription($requestDescription);
             $responseDescription = isset($docsArray[$serviceClassName]['collection'][$httpMethod]['response']) ? $docsArray[$serviceClassName]['collection'][$httpMethod]['response'] : '';
             $op->setResponseDescription($responseDescription);
             $op->setRequiresAuthorization(isset($authorizations['collection'][$httpMethod]) ? $authorizations['collection'][$httpMethod] : false);
             $op->setResponseStatusCodes($this->getStatusCodes($httpMethod, false, $hasFields, $op->requiresAuthorization()));
         }
         if ($isRpc) {
             $description = isset($docsArray[$serviceClassName][$httpMethod]['description']) ? $docsArray[$serviceClassName][$httpMethod]['description'] : '';
             $op->setDescription($description);
             $requestDescription = isset($docsArray[$serviceClassName][$httpMethod]['request']) ? $docsArray[$serviceClassName][$httpMethod]['request'] : '';
             $op->setRequestDescription($requestDescription);
             $responseDescription = isset($docsArray[$serviceClassName][$httpMethod]['response']) ? $docsArray[$serviceClassName][$httpMethod]['response'] : '';
             $op->setResponseDescription($responseDescription);
             $op->setRequiresAuthorization(isset($authorizations['actions'][$serviceData['action']][$httpMethod]) ? $authorizations['actions'][$serviceData['action']][$httpMethod] : false);
             $op->setResponseStatusCodes($this->getStatusCodes($httpMethod, $hasSegments, $hasFields, $op->requiresAuthorization()));
         }
         $ops[] = $op;
     }
     $service->setOperations($ops);
     if (isset($serviceData['entity_http_methods'])) {
         $ops = array();
         foreach ($serviceData['entity_http_methods'] as $httpMethod) {
             $op = new Operation();
             $op->setHttpMethod($httpMethod);
             $description = isset($docsArray[$serviceClassName]['entity'][$httpMethod]['description']) ? $docsArray[$serviceClassName]['entity'][$httpMethod]['description'] : '';
             $op->setDescription($description);
             $requestDescription = isset($docsArray[$serviceClassName]['entity'][$httpMethod]['request']) ? $docsArray[$serviceClassName]['entity'][$httpMethod]['request'] : '';
             $op->setRequestDescription($requestDescription);
             $responseDescription = isset($docsArray[$serviceClassName]['entity'][$httpMethod]['response']) ? $docsArray[$serviceClassName]['entity'][$httpMethod]['response'] : '';
             $op->setResponseDescription($responseDescription);
             $op->setRequiresAuthorization(isset($authorizations['entity'][$httpMethod]) ? $authorizations['entity'][$httpMethod] : false);
             $op->setResponseStatusCodes($this->getStatusCodes($httpMethod, true, $hasFields, $op->requiresAuthorization()));
             $ops[] = $op;
         }
         $service->setEntityOperations($ops);
     }
     if (isset($this->config['zf-content-negotiation']['accept_whitelist'][$serviceClassName])) {
         $service->setRequestAcceptTypes($this->config['zf-content-negotiation']['accept_whitelist'][$serviceClassName]);
     }
     if (isset($this->config['zf-content-negotiation']['content_type_whitelist'][$serviceClassName])) {
         $service->setRequestContentTypes($this->config['zf-content-negotiation']['content_type_whitelist'][$serviceClassName]);
     }
     return $service;
 }