Merge branch 'gerrit/goldfish' into 'master'

Change-Id: Ieaa5758c77aa8445a14b6edcebdf75f300b04b4c
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java
index 0b7e7d0..6928b64 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java
@@ -91,6 +91,7 @@
 import org.apache.asterix.common.metadata.NamespacePathResolver;
 import org.apache.asterix.common.metadata.NamespaceResolver;
 import org.apache.asterix.common.replication.INcLifecycleCoordinator;
+import org.apache.asterix.common.utils.IdentifierUtil;
 import org.apache.asterix.common.utils.Servlets;
 import org.apache.asterix.external.adapter.factory.AdapterFactoryService;
 import org.apache.asterix.file.StorageComponentProvider;
@@ -165,7 +166,7 @@
         ccServiceCtx.setMessageBroker(new CCMessageBroker(controllerService));
         ccServiceCtx.setPersistedResourceRegistry(new PersistedResourceRegistry());
         configureLoggingLevel(ccServiceCtx.getAppConfig().getLoggingLevel(ExternalProperties.Option.LOG_LEVEL));
-        LOGGER.info("Starting Asterix cluster controller");
+        LOGGER.info("Starting {} cluster controller", IdentifierUtil.productName());
         String strIP = ccServiceCtx.getCCContext().getClusterControllerInfo().getClientNetAddress();
         int port = ccServiceCtx.getCCContext().getClusterControllerInfo().getClientNetPort();
         hcc = new HyracksConnection(strIP, port,
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
index 0ff8796..6f8126b 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
@@ -79,6 +79,7 @@
 import org.apache.asterix.common.transactions.IRecoveryManager;
 import org.apache.asterix.common.transactions.IRecoveryManager.SystemState;
 import org.apache.asterix.common.transactions.IRecoveryManagerFactory;
+import org.apache.asterix.common.utils.IdentifierUtil;
 import org.apache.asterix.common.utils.PrintUtil;
 import org.apache.asterix.common.utils.Servlets;
 import org.apache.asterix.common.utils.StorageConstants;
@@ -148,9 +149,7 @@
             throw new IllegalArgumentException("Unrecognized argument(s): " + Arrays.toString(args));
         }
         nodeId = this.ncServiceCtx.getNodeId();
-        if (LOGGER.isInfoEnabled()) {
-            LOGGER.info("Starting Asterix node controller: " + nodeId);
-        }
+        LOGGER.info("Starting {} node controller: {}", IdentifierUtil.productName(), nodeId);
         final NodeControllerService controllerService = (NodeControllerService) ncServiceCtx.getControllerService();
 
         if (System.getProperty("java.rmi.server.hostname") == null) {
@@ -280,9 +279,7 @@
         if (!stopInitiated) {
             runtimeContext.setShuttingdown(true);
             stopInitiated = true;
-            if (LOGGER.isInfoEnabled()) {
-                LOGGER.info("Stopping Asterix node controller: " + nodeId);
-            }
+            LOGGER.info("Stopping {} node controller: {}", IdentifierUtil.productName(), nodeId);
 
             webManager.stop();
 
diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/filesystem/HolePuncherProvider.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/filesystem/HolePuncherProvider.java
index 91de5ae..e50559f 100644
--- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/filesystem/HolePuncherProvider.java
+++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/lazy/filesystem/HolePuncherProvider.java
@@ -52,7 +52,7 @@
 
         // Running a debug hole puncher on a non-Linux box
         String osName = FileSystemOperationDispatcherUtil.getOSName();
-        LOGGER.warn("Using 'DebugHolePuncher' as the OS '{}' does not support punishing holes", osName);
+        LOGGER.warn("Using 'DebugHolePuncher' as the OS '{}' does not support punching holes", osName);
         return new DebugHolePuncher(cloudIOManager, bufferProvider);
     }
 
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java
index b6bce47..ba26ba7 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IIdentifierMapper.java
@@ -19,13 +19,29 @@
 
 package org.apache.asterix.common.api;
 
+import org.apache.commons.lang3.StringUtils;
+
 @FunctionalInterface
 public interface IIdentifierMapper {
 
     enum Modifier {
         SINGULAR,
+        SINGULAR_CAPITALIZED,
         PLURAL,
-        NONE
+        PLURAL_CAPITALIZED,
+        NONE,
+        NONE_CAPITALIZED;
+
+        public String fixup(String input) {
+            switch (this) {
+                case SINGULAR_CAPITALIZED:
+                case PLURAL_CAPITALIZED:
+                case NONE_CAPITALIZED:
+                    return StringUtils.capitalize(input);
+                default:
+                    return input;
+            }
+        }
     }
 
     String map(String identifier, Modifier modifier);
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 3694bb2..3364600 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -18,6 +18,7 @@
  */
 package org.apache.asterix.common.exceptions;
 
+import org.apache.asterix.common.utils.IdentifierUtil;
 import org.apache.hyracks.api.exceptions.IError;
 import org.apache.hyracks.api.util.ErrorMessageUtil;
 
@@ -460,8 +461,8 @@
     }
 
     private static class ErrorMessageMapHolder {
-        private static final String[] enumMessages =
-                ErrorMessageUtil.defineMessageEnumOrdinalMap(values(), RESOURCE_PATH);
+        private static final String[] enumMessages = IdentifierUtil
+                .replaceIdentifiers(ErrorMessageUtil.defineMessageEnumOrdinalMap(values(), RESOURCE_PATH));
 
         private static String get(ErrorCode errorCode) {
             return enumMessages[errorCode.ordinal()];
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java
index 8157125..a32f7f9 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierMappingUtil.java
@@ -21,42 +21,59 @@
 
 import static org.apache.asterix.common.utils.IdentifierUtil.DATASET;
 import static org.apache.asterix.common.utils.IdentifierUtil.DATAVERSE;
+import static org.apache.asterix.common.utils.IdentifierUtil.PRODUCT_ABBREVIATION;
+import static org.apache.asterix.common.utils.IdentifierUtil.PRODUCT_NAME;
 
 import org.apache.asterix.common.api.IIdentifierMapper;
 import org.apache.asterix.common.api.IIdentifierMapper.Modifier;
 
 public class IdentifierMappingUtil {
 
+    private static final String PLAIN_DATASET = "dataset";
     private static final String SINGULAR_DATASET = "a dataset";
     private static final String PLURAL_DATASET = "datasets";
 
+    private static final String PLAIN_DATAVERSE = "dataverse";
     private static final String SINGULAR_DATAVERSE = "a dataverse";
     private static final String PLURAL_DATAVERSE = "dataverses";
 
+    private static final String DEFAULT_PRODUCT_NAME = "Apache AsterixDB";
+    private static final String DEFAULT_PRODUCT_ABBREVIATION = "AsterixDB";
+
     private static final IIdentifierMapper DEFAULT_MAPPER = (identifier, modifier) -> {
         switch (identifier) {
             case DATASET:
                 switch (modifier) {
                     case NONE:
-                        return DATASET;
+                    case NONE_CAPITALIZED:
+                        return modifier.fixup(PLAIN_DATASET);
                     case SINGULAR:
-                        return SINGULAR_DATASET;
+                    case SINGULAR_CAPITALIZED:
+                        return modifier.fixup(SINGULAR_DATASET);
                     case PLURAL:
-                        return PLURAL_DATASET;
+                    case PLURAL_CAPITALIZED:
+                        return modifier.fixup(PLURAL_DATASET);
                     default:
                         throw new IllegalArgumentException("unknown modifier " + modifier);
                 }
             case DATAVERSE:
                 switch (modifier) {
                     case NONE:
-                        return DATAVERSE;
+                    case NONE_CAPITALIZED:
+                        return modifier.fixup(PLAIN_DATAVERSE);
                     case SINGULAR:
-                        return SINGULAR_DATAVERSE;
+                    case SINGULAR_CAPITALIZED:
+                        return modifier.fixup(SINGULAR_DATAVERSE);
                     case PLURAL:
-                        return PLURAL_DATAVERSE;
+                    case PLURAL_CAPITALIZED:
+                        return modifier.fixup(PLURAL_DATAVERSE);
                     default:
                         throw new IllegalArgumentException("unknown modifier " + modifier);
                 }
+            case PRODUCT_NAME:
+                return modifier.fixup(DEFAULT_PRODUCT_NAME);
+            case PRODUCT_ABBREVIATION:
+                return modifier.fixup(DEFAULT_PRODUCT_ABBREVIATION);
             default:
                 throw new IllegalArgumentException("unmapped identifier: " + identifier);
         }
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java
index 88b7190..addc192 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/IdentifierUtil.java
@@ -22,10 +22,22 @@
 import static org.apache.asterix.common.api.IIdentifierMapper.Modifier;
 import static org.apache.asterix.common.api.IIdentifierMapper.Modifier.NONE;
 
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.asterix.common.api.IIdentifierMapper;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 public class IdentifierUtil {
 
-    public static final String DATASET = "dataset";
-    public static final String DATAVERSE = "dataverse";
+    private static final Logger LOGGER = LogManager.getLogger();
+    private static final Pattern MESSAGE_IDENTIFIERS = Pattern.compile("@([A-Z_]*)(:([A-Z_]*))?@");
+
+    public static final String DATASET = "DATASET";
+    public static final String DATAVERSE = "DATAVERSE";
+    public static final String PRODUCT_NAME = "PRODUCT_NAME";
+    public static final String PRODUCT_ABBREVIATION = "PRODUCT_ABBREVIATION";
 
     public static String dataset() {
         return IdentifierMappingUtil.map(DATASET, NONE);
@@ -38,4 +50,41 @@
     public static String dataverse() {
         return IdentifierMappingUtil.map(DATAVERSE, NONE);
     }
+
+    public static String productName() {
+        return IdentifierMappingUtil.map(PRODUCT_NAME, NONE);
+    }
+
+    public static String productAbbreviation() {
+        return IdentifierMappingUtil.map(PRODUCT_ABBREVIATION, NONE);
+    }
+
+    public static String replaceIdentifiers(String input) {
+        if (input == null || input.isEmpty()) {
+            return input;
+        }
+        Matcher m = MESSAGE_IDENTIFIERS.matcher(input);
+        String replacement = m.replaceAll(mr -> {
+            String identifier = mr.group(1);
+            String modifierStr = mr.group(3);
+            IIdentifierMapper.Modifier modifier;
+            if (modifierStr != null) {
+                modifier = IIdentifierMapper.Modifier.valueOf(modifierStr);
+            } else {
+                modifier = IIdentifierMapper.Modifier.NONE;
+            }
+            return IdentifierMappingUtil.map(identifier, modifier);
+        });
+        if (!input.equals(replacement)) {
+            LOGGER.debug("{} -> {}", input, replacement);
+        }
+        return replacement;
+    }
+
+    public static String[] replaceIdentifiers(String[] input) {
+        for (int i = 0; i < input.length; i++) {
+            input[i] = IdentifierUtil.replaceIdentifiers(input[i]);
+        }
+        return input;
+    }
 }