@Override
  public SymbolTable getSymbolTable(String symbolTableName)
  {
    try
    {
      SymbolTableMetadata metadata = _symbolTableNameHandler.extractMetadata(symbolTableName);
      String serverNodeUri = metadata.getServerNodeUri();
      String tableName = metadata.getSymbolTableName();
      boolean isRemote = metadata.isRemote();

      // Check if it's the default table name.
      if (tableName.equals(_defaultResponseSymbolTableName))
      {
        return _defaultResponseSymbolTable;
      }

      // First check the cache.
      SymbolTable symbolTable = _symbolTableNameToSymbolTableCache.getIfPresent(tableName);
      if (symbolTable != null)
      {
        return symbolTable;
      }

      // If this is a local table, and we didn't find it in the cache, cry foul.
      if (!isRemote)
      {
        throw new IllegalStateException("Unable to fetch symbol table with name: " + symbolTableName);
      }

      // Ok, we didn't find it in the cache, let's go query the service the table was served from.
      URI symbolTableUri = new URI(serverNodeUri + "/" + RestLiSymbolTableRequestHandler.SYMBOL_TABLE_URI_PATH + "/" + tableName);
      symbolTable = fetchRemoteSymbolTable(symbolTableUri, Collections.emptyMap(), false);

      if (symbolTable != null)
      {
        // Cache the retrieved table.
        _symbolTableNameToSymbolTableCache.put(tableName, symbolTable);
        return symbolTable;
      }
    }
    catch (URISyntaxException ex)
    {
      LOGGER.error("Failed to construct symbol table URI from symbol table name: " + symbolTableName, ex);
    }

    throw new IllegalStateException("Unable to fetch symbol table with name: " + symbolTableName);
  }
@Test
  public void testGetRemoteSymbolTableFetchSuccess() throws IOException
  {
    RestResponseBuilder builder = new RestResponseBuilder();
    builder.setStatus(200);
    SymbolTable symbolTable = new InMemorySymbolTable("https://OtherHost:100/service|Test--332004310",
        Collections.unmodifiableList(Arrays.asList("Haha", "Hehe")));
    builder.setEntity(SymbolTableSerializer.toByteString(ContentType.PROTOBUF2.getCodec(), symbolTable));
    builder.setHeader(RestConstants.HEADER_CONTENT_TYPE, ContentType.PROTOBUF2.getHeaderKey());
    when(_client.restRequest(eq(new RestRequestBuilder(
            URI.create("https://OtherHost:100/service/symbolTable/Test--332004310"))
            .setHeaders(Collections.singletonMap(RestConstants.HEADER_FETCH_SYMBOL_TABLE, Boolean.TRUE.toString()))
            .build()))).thenReturn(CompletableFuture.completedFuture(builder.build()));

    SymbolTable remoteSymbolTable = _provider.getSymbolTable("https://OtherHost:100/service|Test--332004310");
    Assert.assertNotNull(remoteSymbolTable);
    Assert.assertEquals("https://Host:100/service|Test--332004310", remoteSymbolTable.getName());
    Assert.assertEquals(2, remoteSymbolTable.size());

    // Subsequent fetch should not trigger network fetch and get the table from the cache.
    when(_client.restRequest(any(RestRequest.class))).thenThrow(new IllegalStateException());
    SymbolTable cachedSymbolTable = _provider.getSymbolTable("https://OtherHost:100/service|Test--332004310");
    Assert.assertSame(remoteSymbolTable, cachedSymbolTable);
  }