ACCUMULO-3238 Table.ID Namespace.ID Refactor

* Replaced all occurrences of tableId and namespaceId Strings
  that aren't a part of the user facing API with type safe
  Table.ID and Namespace.ID objects.
* Created new methods in Tables and Namespaces for internal
  use of these type safe objects.


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/d6ea49e0
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/d6ea49e0
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/d6ea49e0

Branch: refs/heads/master
Commit: d6ea49e0344ebe8f840248545821d359853f316a
Parents: 87e5780
Author: Mike Miller <mmil...@apache.org>
Authored: Tue Jul 18 16:45:36 2017 -0400
Committer: Mike Miller <mmil...@apache.org>
Committed: Tue Jul 18 16:45:36 2017 -0400

----------------------------------------------------------------------
 .../core/client/MutationsRejectedException.java |   6 +-
 .../core/client/TableOfflineException.java      |   3 +-
 .../accumulo/core/client/impl/AbstractId.java   |  89 +++++++++
 .../core/client/impl/ActiveScanImpl.java        |   2 +-
 .../core/client/impl/BatchWriterImpl.java       |   4 +-
 .../core/client/impl/ConditionalWriterImpl.java |  12 +-
 .../core/client/impl/ConnectorImpl.java         |   6 +-
 .../client/impl/MultiTableBatchWriterImpl.java  |  23 ++-
 .../accumulo/core/client/impl/Namespace.java    |  42 +++++
 .../client/impl/NamespaceOperationsImpl.java    |  13 +-
 .../accumulo/core/client/impl/Namespaces.java   | 138 +++++++++-----
 .../core/client/impl/OfflineIterator.java       |   4 +-
 .../core/client/impl/OfflineScanner.java        |   4 +-
 .../client/impl/ReplicationOperationsImpl.java  |   6 +-
 .../accumulo/core/client/impl/ScannerImpl.java  |   4 +-
 .../core/client/impl/ScannerIterator.java       |   2 +-
 .../core/client/impl/SyncingTabletLocator.java  |   2 +-
 .../apache/accumulo/core/client/impl/Table.java |  39 ++++
 .../core/client/impl/TableOperationsImpl.java   |  81 +++++----
 .../accumulo/core/client/impl/Tables.java       | 180 +++++++++++--------
 .../core/client/impl/TabletLocator.java         |  12 +-
 .../core/client/impl/TabletLocatorImpl.java     |   8 +-
 .../client/impl/TabletServerBatchDeleter.java   |   4 +-
 .../client/impl/TabletServerBatchReader.java    |   4 +-
 .../impl/TabletServerBatchReaderIterator.java   |  12 +-
 .../client/impl/TabletServerBatchWriter.java    |  54 +++---
 .../core/client/impl/ThriftScanner.java         |  10 +-
 .../core/client/impl/TimeoutTabletLocator.java  |   2 +-
 .../accumulo/core/client/impl/Writer.java       |   4 +-
 .../core/client/mapred/AbstractInputFormat.java |  20 ++-
 .../client/mapred/impl/BatchInputSplit.java     |   3 +-
 .../client/mapreduce/AbstractInputFormat.java   |  20 ++-
 .../client/mapreduce/impl/BatchInputSplit.java  |   5 +-
 .../mapreduce/lib/impl/InputConfigurator.java   |   5 +-
 .../core/client/mock/MockTableOperations.java   |   4 +-
 .../client/mock/impl/MockTabletLocator.java     |   2 +-
 .../accumulo/core/data/impl/KeyExtent.java      |  45 ++---
 .../accumulo/core/data/impl/TabletIdImpl.java   |   2 +-
 .../core/metadata/MetadataServicer.java         |   7 +-
 .../accumulo/core/metadata/MetadataTable.java   |   3 +-
 .../accumulo/core/metadata/RootTable.java       |   3 +-
 .../core/metadata/ServicerForRootTable.java     |   3 +-
 .../core/metadata/ServicerForUserTables.java    |   3 +-
 .../core/metadata/TableMetadataServicer.java    |   7 +-
 .../core/metadata/schema/MetadataScanner.java   |  11 +-
 .../core/metadata/schema/MetadataSchema.java    |  13 +-
 .../core/metadata/schema/TabletMetadata.java    |   5 +-
 .../core/replication/ReplicationSchema.java     |  13 +-
 .../core/replication/ReplicationTable.java      |   3 +-
 .../core/replication/ReplicationTarget.java     |  13 +-
 .../apache/accumulo/core/summary/Gatherer.java  |   5 +-
 .../accumulo/core/util/ByteBufferUtil.java      |   5 +
 .../org/apache/accumulo/core/util/Merge.java    |   3 +-
 .../core/client/impl/ScannerImplTest.java       |   8 +-
 .../client/impl/TableOperationsImplTest.java    |   2 +-
 .../core/client/impl/TabletLocatorImplTest.java |  18 +-
 .../impl/TabletServerBatchReaderTest.java       |   4 +-
 .../mapreduce/impl/BatchInputSplitTest.java     |   5 +-
 .../accumulo/core/data/KeyExtentTest.java       |   9 +-
 .../apache/accumulo/core/data/RangeTest.java    |  22 +--
 .../core/iterators/IteratorUtilTest.java        |  11 +-
 .../iterators/system/MultiIteratorTest.java     |   3 +-
 .../core/metadata/MetadataServicerTest.java     |  11 +-
 .../ReplicationConfigurationUtilTest.java       |   5 +-
 .../core/replication/ReplicationSchemaTest.java |   9 +-
 .../core/replication/ReplicationTargetTest.java |  21 +--
 .../apache/accumulo/core/util/MergeTest.java    |   3 +-
 .../impl/MiniAccumuloClusterImplTest.java       |   4 +-
 .../accumulo/server/client/BulkImporter.java    |   3 +-
 .../server/client/ClientServiceHandler.java     |  42 ++---
 .../server/conf/NamespaceConfWatcher.java       |  16 +-
 .../server/conf/NamespaceConfiguration.java     |   9 +-
 .../server/conf/ServerConfiguration.java        |   6 +-
 .../server/conf/ServerConfigurationFactory.java |  22 +--
 .../accumulo/server/conf/TableConfWatcher.java  |  16 +-
 .../server/conf/TableConfiguration.java         |   9 +-
 .../server/conf/TableParentConfiguration.java   |   8 +-
 .../server/constraints/MetadataConstraints.java |   2 +-
 .../server/fs/PerTableVolumeChooser.java        |   3 +-
 .../server/fs/VolumeChooserEnvironment.java     |   7 +-
 .../accumulo/server/fs/VolumeManager.java       |   3 +-
 .../accumulo/server/fs/VolumeManagerImpl.java   |   5 +-
 .../apache/accumulo/server/init/Initialize.java |   6 +-
 .../accumulo/server/master/LiveTServerSet.java  |   5 +-
 .../master/balancer/ChaoticLoadBalancer.java    |   6 +-
 .../master/balancer/DefaultLoadBalancer.java    |  35 ++--
 .../server/master/balancer/GroupBalancer.java   |   4 +-
 .../balancer/HostRegexTableLoadBalancer.java    |  23 +--
 .../master/balancer/RegexGroupBalancer.java     |   5 +-
 .../master/balancer/TableLoadBalancer.java      |  45 ++---
 .../server/master/balancer/TabletBalancer.java  |   5 +-
 .../server/master/state/CurrentState.java       |   3 +-
 .../master/state/TabletStateChangeIterator.java |  11 +-
 .../accumulo/server/problems/ProblemReport.java |  19 +-
 .../problems/ProblemReportingIterator.java      |   5 +-
 .../server/problems/ProblemReports.java         |  33 ++--
 .../DistributedWorkQueueWorkAssignerHelper.java |   3 +-
 .../server/replication/ReplicationUtil.java     |   5 +-
 .../security/AuditedSecurityOperation.java      |  49 ++---
 .../server/security/SecurityOperation.java      | 108 +++++------
 .../security/handler/InsecurePermHandler.java   |  11 +-
 .../handler/KerberosPermissionHandler.java      |  11 +-
 .../security/handler/PermissionHandler.java     |  14 +-
 .../server/security/handler/ZKAuthorizor.java   |   3 +-
 .../server/security/handler/ZKPermHandler.java  |  26 +--
 .../accumulo/server/tables/TableManager.java    |  36 ++--
 .../accumulo/server/tables/TableObserver.java   |   5 +-
 .../tabletserver/LargestFirstMemoryManager.java |   7 +-
 .../server/util/CheckForMetadataProblems.java   |   2 +-
 .../server/util/FindOfflineTablets.java         |   3 +-
 .../server/util/MasterMetadataUtil.java         |  11 +-
 .../accumulo/server/util/MetadataTableUtil.java |  37 ++--
 .../accumulo/server/util/NamespacePropUtil.java |   7 +-
 .../accumulo/server/util/RandomizeVolumes.java  |   8 +-
 .../util/RemoveEntriesForMissingFiles.java      |   9 +-
 .../server/util/ReplicationTableUtil.java       |   2 +-
 .../accumulo/server/util/TableDiskUsage.java    |   3 +-
 .../accumulo/server/util/TablePropUtil.java     |   9 +-
 .../accumulo/server/util/TabletIterator.java    |   5 +-
 .../server/util/VerifyTabletAssignments.java    |   3 +-
 .../server/client/BulkImporterTest.java         |  11 +-
 .../server/conf/NamespaceConfigurationTest.java |   3 +-
 .../conf/ServerConfigurationFactoryTest.java    |   3 +-
 .../server/conf/TableConfigurationTest.java     |   3 +-
 .../server/fs/VolumeManagerImplTest.java        |   3 +-
 .../BaseHostRegexTableLoadBalancerTest.java     |  31 ++--
 .../balancer/ChaoticLoadBalancerTest.java       |  11 +-
 .../balancer/DefaultLoadBalancerTest.java       |  13 +-
 .../master/balancer/GroupBalancerTest.java      |   3 +-
 ...gexTableLoadBalancerReconfigurationTest.java |   5 +-
 .../HostRegexTableLoadBalancerTest.java         |  13 +-
 .../master/balancer/TableLoadBalancerTest.java  |  27 +--
 .../server/master/state/MergeInfoTest.java      |  25 +--
 .../server/problems/ProblemReportTest.java      |  13 +-
 .../problems/ProblemReportingIteratorTest.java  |   3 +-
 .../server/util/ReplicationTableUtilTest.java   |   7 +-
 .../accumulo/gc/GarbageCollectionAlgorithm.java |   9 +-
 .../gc/GarbageCollectionEnvironment.java        |   5 +-
 .../accumulo/gc/SimpleGarbageCollector.java     |   7 +-
 .../accumulo/gc/GarbageCollectionTest.java      |  21 +--
 .../accumulo/master/FateServiceHandler.java     |  72 ++++----
 .../java/org/apache/accumulo/master/Master.java |  40 +++--
 .../master/MasterClientServiceHandler.java      |  48 ++---
 .../accumulo/master/TabletGroupWatcher.java     |  13 +-
 .../master/replication/FinishedWorkUpdater.java |   7 +-
 .../RemoveCompleteReplicationRecords.java       |  11 +-
 .../replication/SequentialWorkAssigner.java     |  14 +-
 .../master/replication/StatusMaker.java         |   9 +-
 .../accumulo/master/replication/WorkMaker.java  |   5 +-
 .../accumulo/master/state/MergeStats.java       |   3 +-
 .../accumulo/master/state/TableStats.java       |  11 +-
 .../accumulo/master/tableOps/BulkImport.java    |  27 +--
 .../master/tableOps/CancelCompactions.java      |   8 +-
 .../master/tableOps/ChangeTableState.java       |   8 +-
 .../accumulo/master/tableOps/CleanUp.java       |  13 +-
 .../master/tableOps/CleanUpBulkImport.java      |   5 +-
 .../accumulo/master/tableOps/CloneInfo.java     |  11 +-
 .../accumulo/master/tableOps/CloneTable.java    |   7 +-
 .../accumulo/master/tableOps/CompactRange.java  |  16 +-
 .../master/tableOps/CompactionDriver.java       |  17 +-
 .../master/tableOps/CompleteBulkImport.java     |   5 +-
 .../accumulo/master/tableOps/CopyFailed.java    |   5 +-
 .../master/tableOps/CreateImportDir.java        |   2 +-
 .../master/tableOps/CreateNamespace.java        |   3 +-
 .../accumulo/master/tableOps/CreateTable.java   |   6 +-
 .../master/tableOps/DeleteNamespace.java        |   5 +-
 .../accumulo/master/tableOps/DeleteTable.java   |   8 +-
 .../accumulo/master/tableOps/ExportInfo.java    |   7 +-
 .../accumulo/master/tableOps/ExportTable.java   |   4 +-
 .../master/tableOps/FinishCancelCompaction.java |   8 +-
 .../master/tableOps/FinishCreateNamespace.java  |   2 +-
 .../master/tableOps/FinishCreateTable.java      |   2 +-
 .../master/tableOps/FinishImportTable.java      |   2 +-
 .../tableOps/ImportPopulateZookeeper.java       |  11 +-
 .../accumulo/master/tableOps/ImportTable.java   |   6 +-
 .../master/tableOps/ImportedTableInfo.java      |   7 +-
 .../accumulo/master/tableOps/LoadFiles.java     |  11 +-
 .../master/tableOps/MapImportFileNames.java     |   4 +-
 .../master/tableOps/MoveExportedFiles.java      |   8 +-
 .../master/tableOps/NamespaceCleanUp.java       |   5 +-
 .../accumulo/master/tableOps/NamespaceInfo.java |   4 +-
 .../master/tableOps/PopulateMetadataTable.java  |   6 +-
 .../master/tableOps/RenameNamespace.java        |   5 +-
 .../accumulo/master/tableOps/RenameTable.java   |  10 +-
 .../accumulo/master/tableOps/TableInfo.java     |   7 +-
 .../accumulo/master/tableOps/TableRangeOp.java  |  11 +-
 .../master/tableOps/TableRangeOpWait.java       |   8 +-
 .../apache/accumulo/master/tableOps/Utils.java  |  41 +++--
 .../master/tableOps/WriteExportFiles.java       |  24 +--
 .../accumulo/master/util/TableValidators.java   |  16 +-
 ...tributedWorkQueueWorkAssignerHelperTest.java |   5 +-
 .../replication/SequentialWorkAssignerTest.java |  12 +-
 .../replication/UnorderedWorkAssignerTest.java  |   3 +-
 .../master/state/RootTabletStateStoreTest.java  |   3 +-
 .../master/tableOps/ImportTableTest.java        |   3 +-
 .../org/apache/accumulo/monitor/Monitor.java    |   5 +-
 .../rest/problems/ProblemDetailInformation.java |   6 +-
 .../problems/ProblemSummaryInformation.java     |   6 +-
 .../monitor/rest/problems/ProblemsResource.java |  17 +-
 .../rest/replication/ReplicationResource.java   |  14 +-
 .../monitor/rest/tables/TableInformation.java   |   7 +-
 .../monitor/rest/tables/TablesResource.java     |  23 +--
 .../rest/tservers/CurrentOperations.java        |   6 +-
 .../rest/tservers/TabletServerResource.java     |   8 +-
 .../apache/accumulo/monitor/view/WebViews.java  |   5 +-
 .../apache/accumulo/tserver/TabletServer.java   |  72 ++++----
 .../accumulo/tserver/logger/LogReader.java      |   3 +-
 .../replication/ReplicationServicerHandler.java |   4 +-
 .../tserver/session/ConditionalSession.java     |   5 +-
 .../tserver/session/SessionManager.java         |  14 +-
 .../tserver/tablet/DatafileManager.java         |   2 +-
 .../apache/accumulo/tserver/tablet/Tablet.java  |   7 +-
 .../accumulo/tserver/AssignmentWatcherTest.java |   3 +-
 .../tserver/CheckTabletMetadataTest.java        |   7 +-
 .../tserver/LargestFirstMemoryManagerTest.java  |  24 +--
 .../tserver/TabletServerSyncCheckTest.java      |   3 +-
 .../DefaultCompactionStrategyTest.java          |   3 +-
 .../SizeLimitCompactionStrategyTest.java        |   3 +-
 .../TwoTierCompactionStrategyTest.java          |   7 +-
 .../ConfigurableCompactionStrategyTest.java     |   3 +-
 .../accumulo/tserver/log/LogEntryTest.java      |   3 +-
 .../tserver/log/SortedLogRecoveryTest.java      |   3 +-
 .../accumulo/tserver/logger/LogFileTest.java    |   3 +-
 .../replication/AccumuloReplicaSystemTest.java  |  46 ++---
 .../replication/ReplicationProcessorTest.java   |   3 +-
 .../accumulo/shell/commands/DUCommand.java      |   3 +-
 .../shell/commands/DeleteNamespaceCommand.java  |   7 +-
 .../shell/commands/RenameNamespaceCommand.java  |   8 +-
 .../accumulo/shell/commands/TableOperation.java |   6 +-
 .../java/org/apache/accumulo/test/CloneIT.java  |  53 +++---
 .../org/apache/accumulo/test/FileArchiveIT.java |   7 +-
 .../apache/accumulo/test/ImportExportIT.java    |   2 +-
 .../org/apache/accumulo/test/ListTables.java    |   3 +-
 .../org/apache/accumulo/test/LocatorIT.java     |   3 +-
 .../accumulo/test/MetaConstraintRetryIT.java    |   3 +-
 .../MissingWalHeaderCompletesRecoveryIT.java    |   5 +-
 .../org/apache/accumulo/test/NamespacesIT.java  |  12 +-
 .../accumulo/test/QueryMetadataTable.java       |   2 +-
 .../test/RewriteTabletDirectoriesIT.java        |   3 +-
 .../java/org/apache/accumulo/test/SampleIT.java |   3 +-
 .../apache/accumulo/test/SplitRecoveryIT.java   |   3 +-
 .../test/TableConfigurationUpdateIT.java        |   2 +-
 .../apache/accumulo/test/VolumeChooserIT.java   |  19 +-
 .../java/org/apache/accumulo/test/VolumeIT.java |   5 +-
 .../apache/accumulo/test/WrongTabletTest.java   |   5 +-
 .../test/functional/FunctionalTestUtils.java    |   3 +-
 .../test/functional/MasterAssignmentIT.java     |   3 +-
 .../accumulo/test/functional/MergeIT.java       |   7 +-
 .../test/functional/RegexGroupBalanceIT.java    |   5 +-
 .../accumulo/test/functional/SplitIT.java       |   3 +-
 .../test/functional/SplitRecoveryIT.java        |   7 +-
 .../test/functional/TableChangeStateIT.java     |   5 +-
 .../accumulo/test/functional/TableIT.java       |   3 +-
 .../functional/TabletStateChangeIteratorIT.java |  13 +-
 .../accumulo/test/functional/WALSunnyDayIT.java |   2 +-
 .../CloseWriteAheadLogReferencesIT.java         |   3 +-
 .../accumulo/test/master/MergeStateIT.java      |   7 +-
 .../test/master/SuspendedTabletsIT.java         |   2 +-
 .../metadata/MetadataBatchScanTest.java         |   3 +-
 .../performance/scan/CollectTabletStats.java    |   9 +-
 .../test/performance/thrift/NullTserver.java    |   3 +-
 .../test/replication/FinishedWorkUpdaterIT.java |  21 +--
 ...bageCollectorCommunicatesWithTServersIT.java |   3 +-
 .../RemoveCompleteReplicationRecordsIT.java     |  41 +++--
 .../test/replication/ReplicationIT.java         |  29 +--
 .../ReplicationOperationsImplIT.java            |  49 ++---
 .../replication/SequentialWorkAssignerIT.java   |  39 ++--
 .../test/replication/StatusCombinerMacIT.java   |   5 +-
 .../test/replication/StatusMakerIT.java         |   5 +-
 .../replication/UnorderedWorkAssignerIT.java    |   9 +-
 ...UnusedWalDoesntCloseReplicationStatusIT.java |   9 +-
 .../accumulo/test/replication/WorkMakerIT.java  |  11 +-
 272 files changed, 1993 insertions(+), 1446 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
 
b/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
index 8f8720a..2bb348d 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/MutationsRejectedException.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import org.apache.accumulo.core.client.impl.Table;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.security.SecurityErrorCode;
 import org.apache.accumulo.core.data.ConstraintViolationSummary;
@@ -68,13 +69,14 @@ public class MutationsRejectedException extends 
AccumuloException {
     Map<String,Set<SecurityErrorCode>> result = new HashMap<>();
 
     for (Entry<TabletId,Set<SecurityErrorCode>> entry : hashMap.entrySet()) {
-      String tableInfo = Tables.getPrintableTableInfoFromId(instance, 
entry.getKey().getTableId().toString());
+      TabletId tabletId = entry.getKey();
+      String tableInfo = Tables.getPrintableTableInfoFromId(instance, new 
Table.ID(tabletId.getTableId().toString()));
 
       if (!result.containsKey(tableInfo)) {
         result.put(tableInfo, new HashSet<SecurityErrorCode>());
       }
 
-      result.get(tableInfo).addAll(hashMap.get(entry.getKey()));
+      result.get(tableInfo).addAll(hashMap.get(tabletId));
     }
 
     return result.toString();

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java 
b/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java
index ef63228..2afb69d 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/TableOfflineException.java
@@ -16,6 +16,7 @@
  */
 package org.apache.accumulo.core.client;
 
+import org.apache.accumulo.core.client.impl.Table;
 import org.apache.accumulo.core.client.impl.Tables;
 
 public class TableOfflineException extends RuntimeException {
@@ -26,7 +27,7 @@ public class TableOfflineException extends RuntimeException {
     if (tableId == null)
       return " <unknown table> ";
     try {
-      String tableName = Tables.getTableName(instance, tableId);
+      String tableName = Tables.getTableName(instance, new Table.ID(tableId));
       return tableName + " (" + tableId + ")";
     } catch (TableNotFoundException e) {
       return " <unknown table> (" + tableId + ")";

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java
new file mode 100644
index 0000000..9bf7341
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/AbstractId.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.client.impl;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Objects.requireNonNull;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * An abstract identifier class for comparing equality of identifiers of the 
same type.
+ */
+public abstract class AbstractId implements Comparable<AbstractId>, 
Serializable {
+
+  private static final long serialVersionUID = -155513612834787244L;
+  private final String canonical;
+  private Integer hashCode = null;
+
+  protected AbstractId(final String canonical) {
+    requireNonNull(canonical, "canonical cannot be null");
+    this.canonical = canonical;
+  }
+
+  /**
+   * The canonical ID
+   */
+  public final String canonicalID() {
+    return canonical;
+  }
+
+  public boolean isEmpty() {
+    return canonical.isEmpty();
+  }
+
+  /**
+   * AbstractID objects are considered equal if, and only if, they are of the 
same type and have the same canonical identifier.
+   */
+  @Override
+  public boolean equals(final Object obj) {
+    if (this == obj)
+      return true;
+    return obj != null && Objects.equals(getClass(), obj.getClass()) && 
Objects.equals(canonicalID(), ((AbstractId) obj).canonicalID());
+  }
+
+  @Override
+  public int hashCode() {
+    if (hashCode == null) {
+      hashCode = Objects.hash(canonicalID());
+    }
+    return hashCode;
+  }
+
+  /**
+   * Returns a string of the canonical ID
+   */
+  @Override
+  public String toString() {
+    return canonical;
+  }
+
+  /**
+   * Return a UTF_8 byte[] of the canonical ID.
+   */
+  public final byte[] getUtf8() {
+    return canonical.getBytes(UTF_8);
+  }
+
+  @Override
+  public int compareTo(AbstractId id) {
+    requireNonNull(id, "id cannot be null");
+    return this.canonicalID().compareTo(id.canonicalID());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java
index dd96aa3..d962143 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ActiveScanImpl.java
@@ -60,7 +60,7 @@ public class ActiveScanImpl extends ActiveScan {
     this.user = activeScan.user;
     this.age = activeScan.age;
     this.idle = activeScan.idleTime;
-    this.tableName = Tables.getTableName(instance, activeScan.tableId);
+    this.tableName = Tables.getTableName(instance, new 
Table.ID(activeScan.tableId));
     this.type = ScanType.valueOf(activeScan.getType().name());
     this.state = ScanState.valueOf(activeScan.state.name());
     this.extent = new KeyExtent(activeScan.extent);

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java
index 7096187..57129c9 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/BatchWriterImpl.java
@@ -25,10 +25,10 @@ import org.apache.accumulo.core.data.Mutation;
 
 public class BatchWriterImpl implements BatchWriter {
 
-  private final String tableId;
+  private final Table.ID tableId;
   private final TabletServerBatchWriter bw;
 
-  public BatchWriterImpl(ClientContext context, String tableId, 
BatchWriterConfig config) {
+  public BatchWriterImpl(ClientContext context, Table.ID tableId, 
BatchWriterConfig config) {
     checkArgument(context != null, "context is null");
     checkArgument(tableId != null, "tableId is null");
     if (config == null)

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
index 98a15ca..8f2e64f 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
@@ -113,7 +113,7 @@ class ConditionalWriterImpl implements ConditionalWriter {
   private Map<Text,Boolean> cache = Collections.synchronizedMap(new 
LRUMap(1000));
   private final ClientContext context;
   private TabletLocator locator;
-  private final String tableId;
+  private final Table.ID tableId;
   private long timeout;
   private final Durability durability;
   private final String classLoaderContext;
@@ -298,9 +298,9 @@ class ConditionalWriterImpl implements ConditionalWriter {
 
       if (failures.size() == mutations.size())
         if (!Tables.exists(context.getInstance(), tableId))
-          throw new TableDeletedException(tableId);
+          throw new TableDeletedException(tableId.canonicalID());
         else if (Tables.getTableState(context.getInstance(), tableId) == 
TableState.OFFLINE)
-          throw new TableOfflineException(context.getInstance(), tableId);
+          throw new TableOfflineException(context.getInstance(), 
tableId.canonicalID());
 
     } catch (Exception e) {
       for (QCMutation qcm : mutations)
@@ -383,7 +383,7 @@ class ConditionalWriterImpl implements ConditionalWriter {
     }
   }
 
-  ConditionalWriterImpl(ClientContext context, String tableId, 
ConditionalWriterConfig config) {
+  ConditionalWriterImpl(ClientContext context, Table.ID tableId, 
ConditionalWriterConfig config) {
     this.context = context;
     this.auths = config.getAuthorizations();
     this.ve = new VisibilityEvaluator(config.getAuthorizations());
@@ -510,8 +510,8 @@ class ConditionalWriterImpl implements ConditionalWriter {
       }
     }
 
-    TConditionalSession tcs = client.startConditionalUpdate(tinfo, 
context.rpcCreds(), ByteBufferUtil.toByteBuffers(auths.getAuthorizations()), 
tableId,
-        DurabilityImpl.toThrift(durability), this.classLoaderContext);
+    TConditionalSession tcs = client.startConditionalUpdate(tinfo, 
context.rpcCreds(), ByteBufferUtil.toByteBuffers(auths.getAuthorizations()),
+        tableId.canonicalID(), DurabilityImpl.toThrift(durability), 
this.classLoaderContext);
 
     synchronized (cachedSessionIDs) {
       SessionID sid = new SessionID();

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
index 7f8c600..f49e4dc 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
@@ -79,10 +79,10 @@ public class ConnectorImpl extends Connector {
     this.namespaceops = new NamespaceOperationsImpl(context, tableops);
   }
 
-  private String getTableId(String tableName) throws TableNotFoundException {
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+  private Table.ID getTableId(String tableName) throws TableNotFoundException {
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
     if (Tables.getTableState(context.getInstance(), tableId) == 
TableState.OFFLINE)
-      throw new TableOfflineException(context.getInstance(), tableId);
+      throw new TableOfflineException(context.getInstance(), 
tableId.canonicalID());
     return tableId;
   }
 

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
 
b/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
index 15d1c34..34a3137 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/MultiTableBatchWriterImpl.java
@@ -53,9 +53,9 @@ public class MultiTableBatchWriterImpl implements 
MultiTableBatchWriter {
 
   private class TableBatchWriter implements BatchWriter {
 
-    private String tableId;
+    private Table.ID tableId;
 
-    TableBatchWriter(String tableId) {
+    TableBatchWriter(Table.ID tableId) {
       this.tableId = tableId;
     }
 
@@ -85,18 +85,15 @@ public class MultiTableBatchWriterImpl implements 
MultiTableBatchWriter {
   /**
    * CacheLoader which will look up the internal table ID for a given table 
name.
    */
-  private class TableNameToIdLoader extends CacheLoader<String,String> {
+  private class TableNameToIdLoader extends CacheLoader<String,Table.ID> {
 
     @Override
-    public String load(String tableName) throws Exception {
+    public Table.ID load(String tableName) throws Exception {
       Instance instance = context.getInstance();
-      String tableId = Tables.getNameToIdMap(instance).get(tableName);
-
-      if (tableId == null)
-        throw new TableNotFoundException(null, tableName, null);
+      Table.ID tableId = Tables.getTableId(instance, tableName);
 
       if (Tables.getTableState(instance, tableId) == TableState.OFFLINE)
-        throw new TableOfflineException(instance, tableId);
+        throw new TableOfflineException(instance, tableId.canonicalID());
 
       return tableId;
     }
@@ -104,9 +101,9 @@ public class MultiTableBatchWriterImpl implements 
MultiTableBatchWriter {
   }
 
   private TabletServerBatchWriter bw;
-  private ConcurrentHashMap<String,BatchWriter> tableWriters;
+  private ConcurrentHashMap<Table.ID,BatchWriter> tableWriters;
   private final ClientContext context;
-  private final LoadingCache<String,String> nameToIdCache;
+  private final LoadingCache<String,Table.ID> nameToIdCache;
 
   public MultiTableBatchWriterImpl(ClientContext context, BatchWriterConfig 
config) {
     this(context, config, DEFAULT_CACHE_TIME, DEFAULT_CACHE_TIME_UNIT);
@@ -159,7 +156,7 @@ public class MultiTableBatchWriterImpl implements 
MultiTableBatchWriter {
    *          The name of the table which to find the ID for
    * @return The table ID, or null if the table name doesn't exist
    */
-  private String getId(String tableName) throws TableNotFoundException {
+  private Table.ID getId(String tableName) throws TableNotFoundException {
     try {
       return nameToIdCache.get(tableName);
     } catch (UncheckedExecutionException e) {
@@ -217,7 +214,7 @@ public class MultiTableBatchWriterImpl implements 
MultiTableBatchWriter {
       break;
     }
 
-    String tableId = getId(tableName);
+    Table.ID tableId = getId(tableName);
 
     BatchWriter tbw = tableWriters.get(tableId);
     if (tbw == null) {

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java
new file mode 100644
index 0000000..41f8b05
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespace.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.client.impl;
+
+import org.apache.accumulo.core.client.Instance;
+
+public class Namespace {
+
+  /**
+   * Object representing an internal Namespace ID. This class was created to 
help with type safety. For help obtaining the value of a namespace ID from
+   * Zookeeper, see {@link Namespaces#getNamespaceId(Instance, String)}
+   */
+  public static class ID extends AbstractId {
+    private static final long serialVersionUID = 8931104141709170293L;
+
+    public static final ID ACCUMULO = new ID("+accumulo");
+    public static final ID DEFAULT = new ID("+default");
+
+    public ID(String canonical) {
+      super(canonical);
+    }
+  }
+
+  public static final String ACCUMULO = "accumulo";
+  public static final String DEFAULT = "";
+  public static final String SEPARATOR = ".";
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java
 
b/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java
index 0716122..3612865 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/NamespaceOperationsImpl.java
@@ -28,9 +28,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.SortedSet;
+import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.concurrent.TimeUnit;
 
+import java.util.stream.Collectors;
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.IteratorSetting;
@@ -98,7 +100,7 @@ public class NamespaceOperationsImpl extends 
NamespaceOperationsHelper {
       timer = new OpTimer().start();
     }
 
-    boolean exists = 
Namespaces.getNameToIdMap(context.getInstance()).containsKey(namespace);
+    boolean exists = Namespaces.namespaceNameExists(context.getInstance(), 
namespace);
 
     if (timer != null) {
       timer.stop();
@@ -124,7 +126,7 @@ public class NamespaceOperationsImpl extends 
NamespaceOperationsHelper {
   @Override
   public void delete(String namespace) throws AccumuloException, 
AccumuloSecurityException, NamespaceNotFoundException, 
NamespaceNotEmptyException {
     checkArgument(namespace != null, "namespace is null");
-    String namespaceId = Namespaces.getNamespaceId(context.getInstance(), 
namespace);
+    Namespace.ID namespaceId = 
Namespaces.getNamespaceId(context.getInstance(), namespace);
 
     if (namespaceId.equals(Namespaces.ACCUMULO_NAMESPACE_ID) || 
namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) {
       Credentials credentials = context.getCredentials();
@@ -133,7 +135,7 @@ public class NamespaceOperationsImpl extends 
NamespaceOperationsHelper {
     }
 
     if (Namespaces.getTableIds(context.getInstance(), namespaceId).size() > 0) 
{
-      throw new NamespaceNotEmptyException(namespaceId, namespace, null);
+      throw new NamespaceNotEmptyException(namespaceId.canonicalID(), 
namespace, null);
     }
 
     List<ByteBuffer> args = 
Arrays.asList(ByteBuffer.wrap(namespace.getBytes(UTF_8)));
@@ -213,7 +215,10 @@ public class NamespaceOperationsImpl extends 
NamespaceOperationsHelper {
 
   @Override
   public Map<String,String> namespaceIdMap() {
-    return Namespaces.getNameToIdMap(context.getInstance());
+    return Namespaces.getNameToIdMap(context.getInstance()).entrySet().stream()
+        .collect(Collectors.toMap(Map.Entry::getKey, e -> 
e.getValue().canonicalID(), (v1, v2) -> {
+          throw new RuntimeException(String.format("Duplicate key for values 
%s and %s", v1, v2));
+        }, TreeMap::new));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java
index 4eda3db..e4a6730 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Namespaces.java
@@ -18,12 +18,14 @@ package org.apache.accumulo.core.client.impl;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import java.util.function.BiConsumer;
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.NamespaceNotFoundException;
@@ -31,8 +33,12 @@ import org.apache.accumulo.core.util.Validator;
 import org.apache.accumulo.core.zookeeper.ZooUtil;
 import org.apache.accumulo.fate.zookeeper.ZooCache;
 import org.apache.accumulo.fate.zookeeper.ZooCacheFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class Namespaces {
+  private static final Logger log = LoggerFactory.getLogger(Namespaces.class);
+
   public static final String VALID_NAME_REGEX = "^\\w*$";
   public static final Validator<String> VALID_NAME = new Validator<String>() {
     @Override
@@ -72,78 +78,118 @@ public class Namespaces {
     }
   };
 
-  public static final String DEFAULT_NAMESPACE_ID = "+default";
-  public static final String DEFAULT_NAMESPACE = "";
-  public static final String ACCUMULO_NAMESPACE_ID = "+accumulo";
-  public static final String ACCUMULO_NAMESPACE = "accumulo";
+  public static final Namespace.ID DEFAULT_NAMESPACE_ID = Namespace.ID.DEFAULT;
+  public static final String DEFAULT_NAMESPACE = Namespace.DEFAULT;
+  public static final Namespace.ID ACCUMULO_NAMESPACE_ID = 
Namespace.ID.ACCUMULO;
+  public static final String ACCUMULO_NAMESPACE = Namespace.ACCUMULO;
 
   private static ZooCache getZooCache(Instance instance) {
     return new ZooCacheFactory().getZooCache(instance.getZooKeepers(), 
instance.getZooKeepersSessionTimeOut());
   }
 
-  private static SortedMap<String,String> getMap(Instance instance, boolean 
nameAsKey) {
+  public static boolean exists(Instance instance, Namespace.ID namespaceId) {
     ZooCache zc = getZooCache(instance);
-
     List<String> namespaceIds = zc.getChildren(ZooUtil.getRoot(instance) + 
Constants.ZNAMESPACES);
+    return namespaceIds.contains(namespaceId.canonicalID());
+  }
 
-    TreeMap<String,String> namespaceMap = new TreeMap<>();
+  public static List<Table.ID> getTableIds(Instance instance, Namespace.ID 
namespaceId) throws NamespaceNotFoundException {
+    String namespace = getNamespaceName(instance, namespaceId);
+    List<Table.ID> tableIds = new LinkedList<>();
+    for (Entry<String,Table.ID> nameToId : 
Tables.getNameToIdMap(instance).entrySet())
+      if (namespace.equals(Tables.qualify(nameToId.getKey()).getFirst()))
+        tableIds.add(nameToId.getValue());
+    return tableIds;
+  }
 
+  public static List<String> getTableNames(Instance instance, Namespace.ID 
namespaceId) throws NamespaceNotFoundException {
+    String namespace = getNamespaceName(instance, namespaceId);
+    List<String> names = new LinkedList<>();
+    for (String name : Tables.getNameToIdMap(instance).keySet())
+      if (namespace.equals(Tables.qualify(name).getFirst()))
+        names.add(name);
+    return names;
+  }
+
+  /**
+   * Populate map passed in as the BiConsumer. key = ID, value = namespaceName
+   */
+  private static void populateMap(Instance instance, BiConsumer<String,String> 
biConsumer) {
+    final ZooCache zc = getZooCache(instance);
+    List<String> namespaceIds = zc.getChildren(ZooUtil.getRoot(instance) + 
Constants.ZNAMESPACES);
     for (String id : namespaceIds) {
       byte[] path = zc.get(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + 
"/" + id + Constants.ZNAMESPACE_NAME);
       if (path != null) {
-        if (nameAsKey)
-          namespaceMap.put(new String(path, UTF_8), id);
-        else
-          namespaceMap.put(id, new String(path, UTF_8));
+        biConsumer.accept(id, new String(path, UTF_8));
       }
     }
-    return namespaceMap;
   }
 
-  public static boolean exists(Instance instance, String namespaceId) {
-    ZooCache zc = getZooCache(instance);
-    List<String> namespaceIds = zc.getChildren(ZooUtil.getRoot(instance) + 
Constants.ZNAMESPACES);
-    return namespaceIds.contains(namespaceId);
+  /**
+   * Return sorted map with key = ID, value = namespaceName
+   */
+  public static SortedMap<Namespace.ID,String> getIdToNameMap(Instance 
instance) {
+    SortedMap<Namespace.ID,String> idMap = new TreeMap<>();
+    populateMap(instance, (id, name) -> idMap.put(new Namespace.ID(id), name));
+    return idMap;
   }
 
-  public static String getNamespaceId(Instance instance, String namespace) 
throws NamespaceNotFoundException {
-    String id = getNameToIdMap(instance).get(namespace);
-    if (id == null)
-      throw new NamespaceNotFoundException(null, namespace, "getNamespaceId() 
failed to find namespace");
-    return id;
-  }
-
-  public static String getNamespaceName(Instance instance, String namespaceId) 
throws NamespaceNotFoundException {
-    String namespaceName = getIdToNameMap(instance).get(namespaceId);
-    if (namespaceName == null)
-      throw new NamespaceNotFoundException(namespaceId, null, 
"getNamespaceName() failed to find namespace");
-    return namespaceName;
+  /**
+   * Return sorted map with key = namespaceName, value = ID
+   */
+  public static SortedMap<String,Namespace.ID> getNameToIdMap(Instance 
instance) {
+    SortedMap<String,Namespace.ID> nameMap = new TreeMap<>();
+    populateMap(instance, (id, name) -> nameMap.put(name, new 
Namespace.ID(id)));
+    return nameMap;
   }
 
-  public static SortedMap<String,String> getNameToIdMap(Instance instance) {
-    return getMap(instance, true);
+  /**
+   * Look for namespace ID in ZK. Throw NamespaceNotFoundException if not 
found.
+   */
+  public static Namespace.ID getNamespaceId(Instance instance, String 
namespaceName) throws NamespaceNotFoundException {
+    final ArrayList<Namespace.ID> singleId = new ArrayList<>(1);
+    populateMap(instance, (id, name) -> {
+      if (name.equals(namespaceName))
+        singleId.add(new Namespace.ID(id));
+    });
+    if (singleId.isEmpty())
+      throw new NamespaceNotFoundException(null, namespaceName, 
"getNamespaceId() failed to find namespace");
+    return singleId.get(0);
   }
 
-  public static SortedMap<String,String> getIdToNameMap(Instance instance) {
-    return getMap(instance, false);
+  /**
+   * Look for namespace ID in ZK. Fail quietly by logging and returning null.
+   */
+  public static Namespace.ID lookupNamespaceId(Instance instance, String 
namespaceName) {
+    Namespace.ID id = null;
+    try {
+      id = getNamespaceId(instance, namespaceName);
+    } catch (NamespaceNotFoundException e) {
+      if (log.isDebugEnabled())
+        log.debug("Failed to find namespace ID from name: " + namespaceName, 
e);
+    }
+    return id;
   }
 
-  public static List<String> getTableIds(Instance instance, String 
namespaceId) throws NamespaceNotFoundException {
-    String namespace = getNamespaceName(instance, namespaceId);
-    List<String> names = new LinkedList<>();
-    for (Entry<String,String> nameToId : 
Tables.getNameToIdMap(instance).entrySet())
-      if (namespace.equals(Tables.qualify(nameToId.getKey()).getFirst()))
-        names.add(nameToId.getValue());
-    return names;
+  /**
+   * Return true if namespace name exists
+   */
+  public static boolean namespaceNameExists(Instance instance, String 
namespaceName) {
+    return lookupNamespaceId(instance, namespaceName) != null;
   }
 
-  public static List<String> getTableNames(Instance instance, String 
namespaceId) throws NamespaceNotFoundException {
-    String namespace = getNamespaceName(instance, namespaceId);
-    List<String> names = new LinkedList<>();
-    for (String name : Tables.getNameToIdMap(instance).keySet())
-      if (namespace.equals(Tables.qualify(name).getFirst()))
-        names.add(name);
-    return names;
+  /**
+   * Look for namespace name in ZK. Throw NamespaceNotFoundException if not 
found.
+   */
+  public static String getNamespaceName(Instance instance, Namespace.ID 
namespaceId) throws NamespaceNotFoundException {
+    String name;
+    ZooCache zc = getZooCache(instance);
+    byte[] path = zc.get(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES + 
"/" + namespaceId.canonicalID() + Constants.ZNAMESPACE_NAME);
+    if (path != null)
+      name = new String(path, UTF_8);
+    else
+      throw new NamespaceNotFoundException(namespaceId.canonicalID(), null, 
"getNamespaceName() failed to find namespace");
+    return name;
   }
 
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java
index 0546ab9..4d8470b 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java
@@ -146,7 +146,7 @@ class OfflineIterator implements Iterator<Entry<Key,Value>> 
{
   private Range range;
   private KeyExtent currentExtent;
   private Connector conn;
-  private String tableId;
+  private Table.ID tableId;
   private Authorizations authorizations;
   private Instance instance;
   private ScannerOptions options;
@@ -162,7 +162,7 @@ class OfflineIterator implements Iterator<Entry<Key,Value>> 
{
       this.range = range.bound(this.options.fetchedColumns.first(), 
this.options.fetchedColumns.last());
     }
 
-    this.tableId = table.toString();
+    this.tableId = new Table.ID(table.toString());
     this.authorizations = authorizations;
     this.readers = new ArrayList<>();
 

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java
index 427a7cc..8772184 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java
@@ -41,14 +41,14 @@ public class OfflineScanner extends ScannerOptions 
implements Scanner {
   private Authorizations authorizations;
   private Text tableId;
 
-  public OfflineScanner(Instance instance, Credentials credentials, String 
tableId, Authorizations authorizations) {
+  public OfflineScanner(Instance instance, Credentials credentials, Table.ID 
tableId, Authorizations authorizations) {
     checkArgument(instance != null, "instance is null");
     checkArgument(credentials != null, "credentials is null");
     checkArgument(tableId != null, "tableId is null");
     checkArgument(authorizations != null, "authorizations is null");
     this.instance = instance;
     this.credentials = credentials;
-    this.tableId = new Text(tableId);
+    this.tableId = new Text(tableId.getUtf8());
     this.range = new Range((Key) null, (Key) null);
 
     this.authorizations = authorizations;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java
 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java
index ab6160e..79a2dad 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ReplicationOperationsImpl.java
@@ -117,7 +117,7 @@ public class ReplicationOperationsImpl implements 
ReplicationOperations {
     });
   }
 
-  protected String getTableId(Connector conn, String tableName) throws 
AccumuloException, AccumuloSecurityException, TableNotFoundException {
+  protected Table.ID getTableId(Connector conn, String tableName) throws 
AccumuloException, AccumuloSecurityException, TableNotFoundException {
     TableOperations tops = conn.tableOperations();
 
     if (!conn.tableOperations().exists(tableName)) {
@@ -132,7 +132,7 @@ public class ReplicationOperationsImpl implements 
ReplicationOperations {
       }
     }
 
-    return tableId;
+    return new Table.ID(tableId);
   }
 
   @Override
@@ -142,7 +142,7 @@ public class ReplicationOperationsImpl implements 
ReplicationOperations {
     log.debug("Collecting referenced files for replication of table {}", 
tableName);
 
     Connector conn = context.getConnector();
-    String tableId = getTableId(conn, tableName);
+    Table.ID tableId = getTableId(conn, tableName);
 
     log.debug("Found id of {} for name {}", tableId, tableName);
 

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java
index 89406f4..6d4f4b7 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerImpl.java
@@ -46,7 +46,7 @@ public class ScannerImpl extends ScannerOptions implements 
Scanner {
 
   private final ClientContext context;
   private Authorizations authorizations;
-  private String tableId;
+  private Table.ID tableId;
 
   private int size;
 
@@ -54,7 +54,7 @@ public class ScannerImpl extends ScannerOptions implements 
Scanner {
   private boolean isolated = false;
   private long readaheadThreshold = 
Constants.SCANNER_DEFAULT_READAHEAD_THRESHOLD;
 
-  public ScannerImpl(ClientContext context, String tableId, Authorizations 
authorizations) {
+  public ScannerImpl(ClientContext context, Table.ID tableId, Authorizations 
authorizations) {
     checkArgument(context != null, "context is null");
     checkArgument(tableId != null, "tableId is null");
     checkArgument(authorizations != null, "authorizations is null");

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java
index ae55cc0..c24e50b 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/ScannerIterator.java
@@ -104,7 +104,7 @@ public class ScannerIterator implements 
Iterator<Entry<Key,Value>> {
 
   }
 
-  ScannerIterator(ClientContext context, String tableId, Authorizations 
authorizations, Range range, int size, int timeOut, ScannerOptions options,
+  ScannerIterator(ClientContext context, Table.ID tableId, Authorizations 
authorizations, Range range, int size, int timeOut, ScannerOptions options,
       boolean isolated, long readaheadThreshold) {
     this.timeOut = timeOut;
     this.readaheadThreshold = readaheadThreshold;

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java
 
b/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java
index 6e7e072..4c3862f 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/SyncingTabletLocator.java
@@ -51,7 +51,7 @@ public class SyncingTabletLocator extends TabletLocator {
     }
   }
 
-  public SyncingTabletLocator(final ClientContext context, final String 
tableId) {
+  public SyncingTabletLocator(final ClientContext context, final Table.ID 
tableId) {
     this(new Callable<TabletLocator>() {
       @Override
       public TabletLocator call() throws Exception {

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java
new file mode 100644
index 0000000..e20ef01
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Table.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.core.client.impl;
+
+import org.apache.accumulo.core.client.Instance;
+
+public class Table {
+
+  /**
+   * Object representing an internal table ID. This class was created to help 
with type safety. For help obtaining the value of a table ID from Zookeeper, see
+   * {@link Tables#getTableId(Instance, String)}
+   */
+  public static class ID extends AbstractId {
+    private static final long serialVersionUID = 7399913185860577809L;
+
+    public static final ID METADATA = new ID("!0");
+    public static final ID REPLICATION = new ID("+rep");
+    public static final ID ROOT = new ID("+r");
+
+    public ID(final String canonical) {
+      super(canonical);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
 
b/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
index 67c52e2..a5b72c1 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
@@ -359,7 +359,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
         case NAMESPACE_NOTFOUND:
           throw new NamespaceNotFoundException(e);
         case OFFLINE:
-          throw new TableOfflineException(context.getInstance(), 
Tables.getTableId(context.getInstance(), tableOrNamespaceName));
+          throw new TableOfflineException(context.getInstance(), 
Tables.getTableId(context.getInstance(), tableOrNamespaceName).canonicalID());
         default:
           throw new AccumuloException(e.description, e);
       }
@@ -379,12 +379,12 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
   private static class SplitEnv {
     private String tableName;
-    private String tableId;
+    private Table.ID tableId;
     private ExecutorService executor;
     private CountDownLatch latch;
     private AtomicReference<Throwable> exception;
 
-    SplitEnv(String tableName, String tableId, ExecutorService executor, 
CountDownLatch latch, AtomicReference<Throwable> exception) {
+    SplitEnv(String tableName, Table.ID tableId, ExecutorService executor, 
CountDownLatch latch, AtomicReference<Throwable> exception) {
       this.tableName = tableName;
       this.tableId = tableId;
       this.executor = executor;
@@ -435,7 +435,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
   @Override
   public void addSplits(String tableName, SortedSet<Text> partitionKeys) 
throws TableNotFoundException, AccumuloException, AccumuloSecurityException {
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
 
     List<Text> splits = new ArrayList<>(partitionKeys);
     // should be sorted because we copied from a sorted set, but that makes 
assumptions about
@@ -457,7 +457,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
           // user would only have the stack trace for the background thread.
           if (excep instanceof TableNotFoundException) {
             TableNotFoundException tnfe = (TableNotFoundException) excep;
-            throw new TableNotFoundException(tableId, tableName, "Table not 
found by background thread", tnfe);
+            throw new TableNotFoundException(tableId.canonicalID(), tableName, 
"Table not found by background thread", tnfe);
           } else if (excep instanceof AccumuloSecurityException) {
             // base == background accumulo security exception
             AccumuloSecurityException base = (AccumuloSecurityException) excep;
@@ -478,7 +478,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     }
   }
 
-  private void addSplits(String tableName, SortedSet<Text> partitionKeys, 
String tableId) throws AccumuloException, AccumuloSecurityException,
+  private void addSplits(String tableName, SortedSet<Text> partitionKeys, 
Table.ID tableId) throws AccumuloException, AccumuloSecurityException,
       TableNotFoundException, AccumuloServerException {
     TabletLocator tabLocator = TabletLocator.getLocator(context, tableId);
 
@@ -498,9 +498,9 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
         if (tl == null) {
           if (!Tables.exists(context.getInstance(), tableId))
-            throw new TableNotFoundException(tableId, tableName, null);
+            throw new TableNotFoundException(tableId.canonicalID(), tableName, 
null);
           else if (Tables.getTableState(context.getInstance(), tableId) == 
TableState.OFFLINE)
-            throw new TableOfflineException(context.getInstance(), tableId);
+            throw new TableOfflineException(context.getInstance(), 
tableId.canonicalID());
           continue;
         }
 
@@ -539,7 +539,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
         } catch (ThriftSecurityException e) {
           Tables.clearCache(context.getInstance());
           if (!Tables.exists(context.getInstance(), tableId))
-            throw new TableNotFoundException(tableId, tableName, null);
+            throw new TableNotFoundException(tableId.canonicalID(), tableName, 
null);
           throw new AccumuloSecurityException(e.user, e.code, e);
         } catch (NotServingTabletException e) {
           // Do not silently spin when we repeatedly fail to get the location 
for a tablet
@@ -597,7 +597,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
     checkArgument(tableName != null, "tableName is null");
 
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
 
     TreeMap<KeyExtent,String> tabletLocations = new TreeMap<>();
 
@@ -611,7 +611,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
         throw ase;
       } catch (Exception e) {
         if (!Tables.exists(context.getInstance(), tableId)) {
-          throw new TableNotFoundException(tableId, tableName, null);
+          throw new TableNotFoundException(tableId.canonicalID(), tableName, 
null);
         }
 
         if (e instanceof RuntimeException && e.getCause() instanceof 
AccumuloSecurityException) {
@@ -700,7 +700,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     checkArgument(srcTableName != null, "srcTableName is null");
     checkArgument(newTableName != null, "newTableName is null");
 
-    String srcTableId = Tables.getTableId(context.getInstance(), srcTableName);
+    Table.ID srcTableId = Tables.getTableId(context.getInstance(), 
srcTableName);
 
     if (flush)
       _flush(srcTableId, null, null, true);
@@ -711,7 +711,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     if (propertiesToSet == null)
       propertiesToSet = Collections.emptyMap();
 
-    List<ByteBuffer> args = 
Arrays.asList(ByteBuffer.wrap(srcTableId.getBytes(UTF_8)), 
ByteBuffer.wrap(newTableName.getBytes(UTF_8)));
+    List<ByteBuffer> args = 
Arrays.asList(ByteBuffer.wrap(srcTableId.getUtf8()), 
ByteBuffer.wrap(newTableName.getBytes(UTF_8)));
     Map<String,String> opts = new HashMap<>();
     for (Entry<String,String> entry : propertiesToSet.entrySet()) {
       if (entry.getKey().startsWith(CLONE_EXCLUDE_PREFIX))
@@ -749,7 +749,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
   public void flush(String tableName, Text start, Text end, boolean wait) 
throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
     checkArgument(tableName != null, "tableName is null");
 
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
     _flush(tableId, start, end, wait);
   }
 
@@ -787,7 +787,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
       }
     }
 
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
 
     Text start = config.getStartRow();
     Text end = config.getEndRow();
@@ -795,7 +795,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     if (config.getFlush())
       _flush(tableId, start, end, true);
 
-    List<ByteBuffer> args = 
Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8)), start == null ? EMPTY : 
TextUtil.getByteBuffer(start), end == null ? EMPTY
+    List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8()), 
start == null ? EMPTY : TextUtil.getByteBuffer(start), end == null ? EMPTY
         : TextUtil.getByteBuffer(end), 
ByteBuffer.wrap(IteratorUtil.encodeIteratorSettings(config.getIterators())), 
ByteBuffer
         
.wrap(CompactionStrategyConfigUtil.encode(config.getCompactionStrategy())));
 
@@ -815,9 +815,9 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
   @Override
   public void cancelCompaction(String tableName) throws 
AccumuloSecurityException, TableNotFoundException, AccumuloException {
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
 
-    List<ByteBuffer> args = 
Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8)));
+    List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8()));
 
     Map<String,String> opts = new HashMap<>();
     try {
@@ -829,7 +829,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
   }
 
-  private void _flush(String tableId, Text start, Text end, boolean wait) 
throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
+  private void _flush(Table.ID tableId, Text start, Text end, boolean wait) 
throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
 
     try {
       long flushID;
@@ -841,7 +841,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
         MasterClientService.Iface client = null;
         try {
           client = MasterClient.getConnectionWithRetry(context);
-          flushID = client.initiateFlush(Tracer.traceInfo(), 
context.rpcCreds(), tableId);
+          flushID = client.initiateFlush(Tracer.traceInfo(), 
context.rpcCreds(), tableId.canonicalID());
           break;
         } catch (TTransportException tte) {
           log.debug("Failed to call initiateFlush, retrying ... ", tte);
@@ -859,8 +859,8 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
         MasterClientService.Iface client = null;
         try {
           client = MasterClient.getConnectionWithRetry(context);
-          client.waitForFlush(Tracer.traceInfo(), context.rpcCreds(), tableId, 
TextUtil.getByteBuffer(start), TextUtil.getByteBuffer(end), flushID,
-              wait ? Long.MAX_VALUE : 1);
+          client.waitForFlush(Tracer.traceInfo(), context.rpcCreds(), 
tableId.canonicalID(), TextUtil.getByteBuffer(start), 
TextUtil.getByteBuffer(end),
+              flushID, wait ? Long.MAX_VALUE : 1);
           break;
         } catch (TTransportException tte) {
           log.debug("Failed to call initiateFlush, retrying ... ", tte);
@@ -876,7 +876,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     } catch (ThriftSecurityException e) {
       switch (e.getCode()) {
         case TABLE_DOESNT_EXIST:
-          throw new TableNotFoundException(tableId, null, e.getMessage(), e);
+          throw new TableNotFoundException(tableId.canonicalID(), null, 
e.getMessage(), e);
         default:
           log.debug("flush security exception on table id {}", tableId);
           throw new AccumuloSecurityException(e.user, e.code, e);
@@ -1029,15 +1029,15 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
     Random random = new Random();
     Map<String,Map<KeyExtent,List<Range>>> binnedRanges = new HashMap<>();
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
     TabletLocator tl = TabletLocator.getLocator(context, tableId);
     // its possible that the cache could contain complete, but old information 
about a tables tablets... so clear it
     tl.invalidateCache();
     while (!tl.binRanges(context, Collections.singletonList(range), 
binnedRanges).isEmpty()) {
       if (!Tables.exists(context.getInstance(), tableId))
-        throw new TableDeletedException(tableId);
+        throw new TableDeletedException(tableId.canonicalID());
       if (Tables.getTableState(context.getInstance(), tableId) == 
TableState.OFFLINE)
-        throw new TableOfflineException(context.getInstance(), tableId);
+        throw new TableOfflineException(context.getInstance(), 
tableId.canonicalID());
 
       log.warn("Unable to locate bins for specified range. Retrying.");
       // sleep randomly between 100 and 200ms
@@ -1135,7 +1135,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     }
   }
 
-  private void waitForTableStateTransition(String tableId, TableState 
expectedState) throws AccumuloException, TableNotFoundException,
+  private void waitForTableStateTransition(Table.ID tableId, TableState 
expectedState) throws AccumuloException, TableNotFoundException,
       AccumuloSecurityException {
 
     Text startRow = null;
@@ -1147,7 +1147,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
         Tables.clearCache(context.getInstance());
         if (Tables.getTableState(context.getInstance(), tableId) != 
expectedState) {
           if (!Tables.exists(context.getInstance(), tableId))
-            throw new TableDeletedException(tableId);
+            throw new TableDeletedException(tableId.canonicalID());
           throw new AccumuloException("Unexpected table state " + tableId + " 
" + Tables.getTableState(context.getInstance(), tableId) + " != " + 
expectedState);
         }
       }
@@ -1269,8 +1269,8 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
   public void offline(String tableName, boolean wait) throws 
AccumuloSecurityException, AccumuloException, TableNotFoundException {
 
     checkArgument(tableName != null, "tableName is null");
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
-    List<ByteBuffer> args = 
Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8)));
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
+    List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8()));
     Map<String,String> opts = new HashMap<>();
 
     try {
@@ -1293,7 +1293,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
   public void online(String tableName, boolean wait) throws 
AccumuloSecurityException, AccumuloException, TableNotFoundException {
     checkArgument(tableName != null, "tableName is null");
 
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
 
     /**
      * ACCUMULO-4574 if table is already online return without executing fate 
operation.
@@ -1304,7 +1304,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
       return;
     }
 
-    List<ByteBuffer> args = 
Arrays.asList(ByteBuffer.wrap(tableId.getBytes(UTF_8)));
+    List<ByteBuffer> args = Arrays.asList(ByteBuffer.wrap(tableId.getUtf8()));
     Map<String,String> opts = new HashMap<>();
 
     try {
@@ -1327,7 +1327,10 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
   @Override
   public Map<String,String> tableIdMap() {
-    return Tables.getNameToIdMap(context.getInstance());
+    return Tables.getNameToIdMap(context.getInstance()).entrySet().stream()
+        .collect(Collectors.toMap(Entry::getKey, e -> 
e.getValue().canonicalID(), (v1, v2) -> {
+          throw new RuntimeException(String.format("Duplicate key for values 
%s and %s", v1, v2));
+        }, TreeMap::new));
   }
 
   @Override
@@ -1646,7 +1649,7 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     requireNonNull(tableName, "tableName must be non null");
     requireNonNull(ranges, "ranges must be non null");
 
-    String tableId = Tables.getTableId(context.getInstance(), tableName);
+    Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
     TabletLocator locator = TabletLocator.getLocator(context, tableId);
 
     List<Range> rangeList = null;
@@ -1665,9 +1668,9 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
     while (!locator.binRanges(context, rangeList, binnedRanges).isEmpty()) {
 
       if (!Tables.exists(context.getInstance(), tableId))
-        throw new TableNotFoundException(tableId, tableName, null);
+        throw new TableNotFoundException(tableId.canonicalID(), tableName, 
null);
       if (Tables.getTableState(context.getInstance(), tableId) == 
TableState.OFFLINE)
-        throw new TableOfflineException(context.getInstance(), tableId);
+        throw new TableOfflineException(context.getInstance(), 
tableId.canonicalID());
 
       binnedRanges.clear();
 
@@ -1711,12 +1714,12 @@ public class TableOperationsImpl extends 
TableOperationsHelper {
 
       @Override
       public List<Summary> retrieve() throws AccumuloException, 
AccumuloSecurityException, TableNotFoundException {
-        String tableId = Tables.getTableId(context.getInstance(), tableName);
+        Table.ID tableId = Tables.getTableId(context.getInstance(), tableName);
         if (Tables.getTableState(context.getInstance(), tableId) == 
TableState.OFFLINE)
-          throw new TableOfflineException(context.getInstance(), tableId);
+          throw new TableOfflineException(context.getInstance(), 
tableId.canonicalID());
 
         TRowRange range = new TRowRange(TextUtil.getByteBuffer(startRow), 
TextUtil.getByteBuffer(endRow));
-        TSummaryRequest request = new TSummaryRequest(tableId, range, 
summariesToFetch, summarizerClassRegex);
+        TSummaryRequest request = new TSummaryRequest(tableId.canonicalID(), 
range, summariesToFetch, summarizerClassRegex);
         if (flush) {
           _flush(tableId, startRow, endRow, true);
         }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
index 5c3c0f6..b1d1cad 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
@@ -19,6 +19,7 @@ package org.apache.accumulo.core.client.impl;
 import static com.google.common.base.Preconditions.checkArgument;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -26,6 +27,7 @@ import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicLong;
 
+import java.util.function.BiConsumer;
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.NamespaceNotFoundException;
@@ -50,48 +52,11 @@ public class Tables {
     return new ZooCacheFactory().getZooCache(instance.getZooKeepers(), 
instance.getZooKeepersSessionTimeOut());
   }
 
-  private static SortedMap<String,String> getMap(Instance instance, boolean 
nameAsKey) {
-    ZooCache zc = getZooCache(instance);
-
-    List<String> tableIds = zc.getChildren(ZooUtil.getRoot(instance) + 
Constants.ZTABLES);
-    TreeMap<String,String> tableMap = new TreeMap<>();
-    Map<String,String> namespaceIdToNameMap = new HashMap<>();
-
-    for (String tableId : tableIds) {
-      byte[] tableName = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES 
+ "/" + tableId + Constants.ZTABLE_NAME);
-      byte[] nId = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" 
+ tableId + Constants.ZTABLE_NAMESPACE);
-      String namespaceName = Namespaces.DEFAULT_NAMESPACE;
-      // create fully qualified table name
-      if (nId == null) {
-        namespaceName = null;
-      } else {
-        String namespaceId = new String(nId, UTF_8);
-        if (!namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) {
-          try {
-            namespaceName = namespaceIdToNameMap.get(namespaceId);
-            if (namespaceName == null) {
-              namespaceName = Namespaces.getNamespaceName(instance, 
namespaceId);
-              namespaceIdToNameMap.put(namespaceId, namespaceName);
-            }
-          } catch (NamespaceNotFoundException e) {
-            log.error("Table (" + tableId + ") contains reference to namespace 
(" + namespaceId + ") that doesn't exist", e);
-            continue;
-          }
-        }
-      }
-      if (tableName != null && namespaceName != null) {
-        String tableNameStr = qualified(new String(tableName, UTF_8), 
namespaceName);
-        if (nameAsKey)
-          tableMap.put(tableNameStr, tableId);
-        else
-          tableMap.put(tableId, tableNameStr);
-      }
-    }
-
-    return tableMap;
-  }
-
-  public static String getTableId(Instance instance, String tableName) throws 
TableNotFoundException {
+  /**
+   * Lookup table ID in ZK. Throw TableNotFoundException if not found. Also 
wraps NamespaceNotFoundException in TableNotFoundException if namespace is not
+   * found.
+   */
+  public static Table.ID getTableId(Instance instance, String tableName) 
throws TableNotFoundException {
     try {
       return _getTableId(instance, tableName);
     } catch (NamespaceNotFoundException e) {
@@ -99,12 +64,15 @@ public class Tables {
     }
   }
 
-  public static String _getTableId(Instance instance, String tableName) throws 
NamespaceNotFoundException, TableNotFoundException {
-    String tableId = getNameToIdMap(instance).get(tableName);
+  /**
+   * Lookup table ID in ZK. If not found, clears cache and tries again.
+   */
+  public static Table.ID _getTableId(Instance instance, String tableName) 
throws NamespaceNotFoundException, TableNotFoundException {
+    Table.ID tableId = lookupTableId(instance, tableName);
     if (tableId == null) {
       // maybe the table exist, but the cache was not updated yet... so try to 
clear the cache and check again
       clearCache(instance);
-      tableId = getNameToIdMap(instance).get(tableName);
+      tableId = lookupTableId(instance, tableName);
       if (tableId == null) {
         String namespace = qualify(tableName).getFirst();
         if (Namespaces.getNameToIdMap(instance).containsKey(namespace))
@@ -116,25 +84,12 @@ public class Tables {
     return tableId;
   }
 
-  public static String getTableName(Instance instance, String tableId) throws 
TableNotFoundException {
-    String tableName = getIdToNameMap(instance).get(tableId);
-    if (tableName == null)
-      throw new TableNotFoundException(tableId, null, null);
-    return tableName;
-  }
-
-  public static SortedMap<String,String> getNameToIdMap(Instance instance) {
-    return getMap(instance, true);
-  }
-
-  public static SortedMap<String,String> getIdToNameMap(Instance instance) {
-    return getMap(instance, false);
-  }
-
-  public static boolean exists(Instance instance, String tableId) {
+  public static boolean exists(Instance instance, Table.ID tableId) {
+    if (tableId == null)
+      return false;
     ZooCache zc = getZooCache(instance);
     List<String> tableIds = zc.getChildren(ZooUtil.getRoot(instance) + 
Constants.ZTABLES);
-    return tableIds.contains(tableId);
+    return tableIds.contains(tableId.canonicalID());
   }
 
   public static void clearCache(Instance instance) {
@@ -165,32 +120,27 @@ public class Tables {
 
   }
 
-  public static String getPrintableTableNameFromId(Map<String,String> 
tidToNameMap, String tableId) {
-    String tableName = tidToNameMap.get(tableId);
-    return tableName == null ? "(ID:" + tableId + ")" : tableName;
-  }
-
-  public static String getPrintableTableInfoFromId(Instance instance, String 
tableId) {
+  public static String getPrintableTableInfoFromId(Instance instance, Table.ID 
tableId) {
     String tableName = null;
     try {
       tableName = getTableName(instance, tableId);
     } catch (TableNotFoundException e) {
       // handled in the string formatting
     }
-    return tableName == null ? String.format("?(ID:%s)", tableId) : 
String.format("%s(ID:%s)", tableName, tableId);
+    return tableName == null ? String.format("?(ID:%s)", 
tableId.canonicalID()) : String.format("%s(ID:%s)", tableName, 
tableId.canonicalID());
   }
 
   public static String getPrintableTableInfoFromName(Instance instance, String 
tableName) {
-    String tableId = null;
+    Table.ID tableId = null;
     try {
       tableId = getTableId(instance, tableName);
     } catch (TableNotFoundException e) {
       // handled in the string formatting
     }
-    return tableId == null ? String.format("%s(?)", tableName) : 
String.format("%s(ID:%s)", tableName, tableId);
+    return tableId == null ? String.format("%s(?)", tableName) : 
String.format("%s(ID:%s)", tableName, tableId.canonicalID());
   }
 
-  public static TableState getTableState(Instance instance, String tableId) {
+  public static TableState getTableState(Instance instance, Table.ID tableId) {
     return getTableState(instance, tableId, false);
   }
 
@@ -206,9 +156,9 @@ public class Tables {
    *          if true clear the table state in zookeeper before checking status
    * @return the table state.
    */
-  public static TableState getTableState(Instance instance, String tableId, 
boolean clearCachedState) {
+  public static TableState getTableState(Instance instance, Table.ID tableId, 
boolean clearCachedState) {
 
-    String statePath = ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + 
tableId + Constants.ZTABLE_STATE;
+    String statePath = ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" + 
tableId.canonicalID() + Constants.ZTABLE_STATE;
 
     if (clearCachedState) {
       Tables.clearCacheByPath(instance, statePath);
@@ -266,7 +216,7 @@ public class Tables {
    * @throws IllegalArgumentException
    *           if the table doesn't exist in ZooKeeper
    */
-  public static String getNamespaceId(Instance instance, String tableId) 
throws TableNotFoundException {
+  public static Namespace.ID getNamespaceId(Instance instance, Table.ID 
tableId) throws TableNotFoundException {
     checkArgument(instance != null, "instance is null");
     checkArgument(tableId != null, "tableId is null");
 
@@ -275,10 +225,86 @@ public class Tables {
 
     // We might get null out of ZooCache if this tableID doesn't exist
     if (null == n) {
-      throw new TableNotFoundException(tableId, null, null);
+      throw new TableNotFoundException(tableId.canonicalID(), null, null);
     }
 
-    return new String(n, UTF_8);
+    return new Namespace.ID(new String(n, UTF_8));
+  }
+
+  /**
+   * Get all table Ids and table names from ZK. The biConsumer accepts the 
first arg (t) as the table ID and second arg (u) as the table name.
+   */
+  private static void getAllTables(Instance instance, 
BiConsumer<String,String> biConsumer) {
+    ZooCache zc = getZooCache(instance);
+    List<String> tableIds = zc.getChildren(ZooUtil.getRoot(instance) + 
Constants.ZTABLES);
+    Map<Namespace.ID,String> namespaceIdToNameMap = new HashMap<>();
+
+    for (String tableId : tableIds) {
+      byte[] tableName = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES 
+ "/" + tableId + Constants.ZTABLE_NAME);
+      byte[] nId = zc.get(ZooUtil.getRoot(instance) + Constants.ZTABLES + "/" 
+ tableId + Constants.ZTABLE_NAMESPACE);
+      String namespaceName = Namespaces.DEFAULT_NAMESPACE;
+      // create fully qualified table name
+      if (nId == null) {
+        namespaceName = null;
+      } else {
+        Namespace.ID namespaceId = new Namespace.ID(new String(nId, UTF_8));
+        if (!namespaceId.equals(Namespaces.DEFAULT_NAMESPACE_ID)) {
+          try {
+            namespaceName = namespaceIdToNameMap.get(namespaceId);
+            if (namespaceName == null) {
+              namespaceName = Namespaces.getNamespaceName(instance, 
namespaceId);
+              namespaceIdToNameMap.put(namespaceId, namespaceName);
+            }
+          } catch (NamespaceNotFoundException e) {
+            log.error("Table (" + tableId + ") contains reference to namespace 
(" + namespaceId + ") that doesn't exist", e);
+            continue;
+          }
+        }
+      }
+      if (tableName != null && namespaceName != null) {
+        String tableNameStr = qualified(new String(tableName, UTF_8), 
namespaceName);
+        biConsumer.accept(tableId, tableNameStr);
+      }
+    }
+  }
+
+  public static SortedMap<Table.ID,String> getIdToNameMap(Instance instance) {
+    SortedMap<Table.ID,String> map = new TreeMap<>();
+    getAllTables(instance, (id, name) -> map.put(new Table.ID(id), name));
+    return map;
+  }
+
+  public static SortedMap<String,Table.ID> getNameToIdMap(Instance instance) {
+    SortedMap<String,Table.ID> map = new TreeMap<>();
+    getAllTables(instance, (id, name) -> map.put(name, new Table.ID(id)));
+    return map;
+  }
+
+  /**
+   * Lookup the table name in ZK. Fail quietly, returning null if not found.
+   */
+  public static Table.ID lookupTableId(Instance instance, String tableName) {
+    ArrayList<Table.ID> singleId = new ArrayList<>(1);
+    getAllTables(instance, (id, name) -> {
+      if (name.equals(tableName))
+        singleId.add(new Table.ID(id));
+    });
+    if (singleId.isEmpty())
+      return null;
+    else
+      return singleId.get(0);
+  }
+
+  public static String getTableName(Instance instance, Table.ID tableId) 
throws TableNotFoundException {
+    ArrayList<String> singleName = new ArrayList<>(1);
+    getAllTables(instance, (id, name) -> {
+      if (id.equals(tableId.canonicalID()))
+        singleName.add(name);
+    });
+    if (singleName.isEmpty())
+      throw new TableNotFoundException(tableId.canonicalID(), null, null);
+
+    return singleName.get(0);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/d6ea49e0/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java 
b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
index 9229643..de7b12b 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletLocator.java
@@ -74,16 +74,16 @@ public abstract class TabletLocator {
 
   private static class LocatorKey {
     String instanceId;
-    String tableName;
+    Table.ID tableId;
 
-    LocatorKey(String instanceId, String table) {
+    LocatorKey(String instanceId, Table.ID table) {
       this.instanceId = instanceId;
-      this.tableName = table;
+      this.tableId = table;
     }
 
     @Override
     public int hashCode() {
-      return instanceId.hashCode() + tableName.hashCode();
+      return instanceId.hashCode() + tableId.hashCode();
     }
 
     @Override
@@ -94,7 +94,7 @@ public abstract class TabletLocator {
     }
 
     public boolean equals(LocatorKey lk) {
-      return instanceId.equals(lk.instanceId) && 
tableName.equals(lk.tableName);
+      return instanceId.equals(lk.instanceId) && tableId.equals(lk.tableId);
     }
 
   }
@@ -108,7 +108,7 @@ public abstract class TabletLocator {
     locators.clear();
   }
 
-  public static synchronized TabletLocator getLocator(ClientContext context, 
String tableId) {
+  public static synchronized TabletLocator getLocator(ClientContext context, 
Table.ID tableId) {
     Instance instance = context.getInstance();
     LocatorKey key = new LocatorKey(instance.getInstanceID(), tableId);
     TabletLocator tl = locators.get(key);

Reply via email to