/*
 * Licensed to the University of California, Berkeley 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 tachyon;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import tachyon.conf.TachyonConf;
import tachyon.Constants;

/**
 * Validate the TachyonConf object.
 *
 */
public class ValidateConf {
  private static final Logger LOG = LoggerFactory.getLogger(Constants.LOGGER_TYPE);

  private static boolean validate() {
    Constants constants = new Constants();
    Set<String> validProperties = new HashSet<String>();
    try {
      // Iterate over the array of Field objects in tachyon.Conatants by reflection
      for (Field field : constants.getClass().getDeclaredFields()) {
        if (field.getType().isAssignableFrom(String.class)) {
          String name = (String) field.get(constants);
          if (name.startsWith("tachyon.")) {
            validProperties.add(name.trim());
          }
        }
      }
    } catch (Exception e) {
      LOG.error(e.getMessage(), e);
    }

    // There are two properties that are defined in tachyon-default.properties but not declared in
    // Tachyon.Constants.
    validProperties.add("tachyon.version");
    validProperties.add("tachyon.debug");

    // There are three properties that are auto-generated in WorkerStorage rather than defined in
    // Tachyon.Constants.
    Pattern aliasPattern = Pattern.compile("tachyon.worker.tieredstore.level\\d+.alias");
    Pattern dirsPathPattern = Pattern.compile("tachyon.worker.tieredstore.level\\d+.dirs.path");
    Pattern dirsQuotaPattern = Pattern.compile("tachyon.worker.tieredstore.level\\d+.dirs.quota");

    TachyonConf tachyonConf = new TachyonConf();
    boolean valid = true;
    for (Entry<String, String> entry : tachyonConf.toMap().entrySet()) {
      String propertyName = entry.getKey();
      if (aliasPattern.matcher(propertyName).matches()
          || dirsPathPattern.matcher(propertyName).matches()
          || dirsQuotaPattern.matcher(propertyName).matches()) {
        continue;
      }
      if (propertyName.startsWith("tachyon.") && !validProperties.contains(propertyName)) {
        System.err.println("Unsupported or deprecated property " + propertyName);
        valid = false;
      }
    }
    return valid;
  }

  public static void main(String[] args) {
    if (!validate()) {
      System.exit(-1);
    }
    System.exit(0);
  }

}

@@ -2124,38 +2124,38 @@
 age 
-rather than defined 
+based on correspond
 in
+g
 %0A    // 
 Tach
@@ -2154,78 +2154,245 @@
  // 
-Tachyon.Constants.%0A    Pattern aliasPattern = Pattern.compile(
+format strings defined in Tachyon.Constants. Here we transform each format string to a regexp%0A    // to check if a property name follows the format. E.g.,%0A    // %22tachyon.worker.tieredstore.leve%25d.alias%22 is transformed to%0A    // 
 %22tachyon
 .wor
@@ -2379,39 +2379,41 @@
 %0A    // %22tachyon
+%5C
 .worker
+%5C
 .tieredstore.lev
@@ -2412,27 +2412,27 @@
 tore
+%5C
 .level%5C
-%5C
 d+
+%5C
 .alias%22
-);
+.
 %0A   
@@ -2440,24 +2440,21 @@
 Pattern 
-dirsPath
+alias
 Pattern 
@@ -2446,32 +2446,40 @@
 n aliasPattern =
+%0A       
  Pattern.compile
@@ -2483,56 +2483,279 @@
 ile(
-%22tachyon.worker.tieredstore.level%5C%5Cd+.dirs.path%22
+Constants.WORKER_TIERED_STORAGE_LEVEL_ALIAS_FORMAT.replace(%22%25d%22, %22%5C%5Cd+%22)%0A            .replace(%22.%22, %22%5C%5C.%22));%0A    Pattern dirsPathPattern =%0A        Pattern.compile(Constants.WORKER_TIERED_STORAGE_LEVEL_DIRS_PATH_FORMAT%0A            .replace(%22%25d%22, %22%5C%5Cd+%22).replace(%22.%22, %22%5C%5C.%22)
 );%0A 
@@ -2783,16 +2783,24 @@
 attern =
+%0A       
  Pattern
@@ -2812,61 +2812,120 @@
 ile(
-%22tachyon.worker.tieredstore.level%5C%5Cd+.dirs.quota%22
+Constants.WORKER_TIERED_STORAGE_LEVEL_DIRS_QUOTA_FORMAT.replace(%22%25d%22,%0A            %22%5C%5Cd+%22).replace(%22.%22, %22%5C%5C.%22)
 );%0A
-%0A
     

Update ValidateConf.java to use templates