private function retrieveMetadata( $entityLogicalName, $force = false ) {
        // check memory
        if ( array_key_exists( $entityLogicalName, $this->cachedEntityDefinitions ) ) {
            return $this->cachedEntityDefinitions[ $entityLogicalName ];
        }

        // check storage
        if ( $this->storage->exists( $entityLogicalName ) ) {
            $entityMetadata                                      = $this->storage->get( $entityLogicalName );
            $this->cachedEntityDefinitions[ $entityLogicalName ] = $entityMetadata;

            return $entityMetadata;
        }

        /**
         * Fetch metadata from CRM and store it in memory and storage (if available).
         *
         * If no storage is available, data will be fetched from the CRM on every SDK execution
         * (web request, cli run).
         */
        $client                                              = $this->client;
        $entityObject                                        = $client->retrieveEntity( $entityLogicalName );
        $metadata                                            = new Metadata( $entityLogicalName, $entityObject );
        $this->cachedEntityDefinitions[ $entityLogicalName ] = $metadata;

        $this->storage->set( $entityLogicalName, $metadata );

        return $metadata;
    }