Add international basic service module
authoryoubowu <wu.youbo@zte.com.cn>
Wed, 8 Feb 2017 02:58:20 +0000 (10:58 +0800)
committer6092002067 <wu.youbo@zte.com.cn>
Mon, 13 Feb 2017 03:24:21 +0000 (11:24 +0800)
Issue-ID:HOLMES-33

Change-Id: I2442ebfa65c6586a21655b226699b0dfbcbb3910
Signed-off-by: youbowu<wu.youbo@zte.com.cn>
12 files changed:
baseservice-i18n/pom.xml [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/DefaultErrorCodeI18n.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/DefaultI18nService.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/ErrorCodeException.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/ErrorCodeI18n.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18n.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nContainer.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nImpl.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nItem.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nJsonUtil.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nService.java [new file with mode: 0644]
baseservice-i18n/src/main/java/org/openo/baseservice/i18n/JsonResourceScanner.java [new file with mode: 0644]

diff --git a/baseservice-i18n/pom.xml b/baseservice-i18n/pom.xml
new file mode 100644 (file)
index 0000000..d110db3
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2017 ZTE Corporation. Licensed 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.openo.common-services.common-utilities</groupId>
+        <artifactId>common-setting</artifactId>
+        <version>1.1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>baseservice-i18n</artifactId>
+    <name>common-services-common-utilities/baseservice-i18n</name>
+    <dependencies>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.10</version>
+        </dependency>
+        <dependency>
+            <groupId>io.dropwizard</groupId>
+            <artifactId>dropwizard-core</artifactId>
+            <version>0.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+            <version>4.8.2</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.3</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-enforcer-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/DefaultErrorCodeI18n.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/DefaultErrorCodeI18n.java
new file mode 100644 (file)
index 0000000..d225e1b
--- /dev/null
@@ -0,0 +1,278 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public final class DefaultErrorCodeI18n implements ErrorCodeI18n {
+
+    static final Logger logger = LoggerFactory.getLogger(DefaultErrorCodeI18n.class);
+    private static DefaultErrorCodeI18n singleton;
+    private static final Lock lock = new ReentrantLock();
+    private Map<Integer, ErrorItemImpl> errorItems;
+
+    private DefaultErrorCodeI18n() {
+        try {
+            init();
+        } catch (Exception e) {
+            logger.error("init ErrorCodeI18n failed.", e);
+        }
+    }
+
+    private void init() throws Exception {
+        final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+        final Map<Integer, ErrorItemImpl> errorItems = new HashMap<Integer, DefaultErrorCodeI18n.ErrorItemImpl>();
+        JsonResourceScanner.findErrorCodePaths().forEach(path -> {
+            HashMap<String, Object> fileValues = null;
+            try (InputStream ins = systemClassLoader.getResourceAsStream(path)) {
+                fileValues = I18nJsonUtil.getInstance().readFromJson(ins, HashMap.class);
+                logger.info("load errorcode file success: " + path);
+            } catch (IOException ex) {
+                logger.info("load errorcode file failed: " + path);
+                logger.info(
+                        "load errorcode file failed: " + systemClassLoader.getResource(path).toString(),
+                        ex);
+                return;
+            }
+            List<?> errcodes = (List<?>) fileValues.get("errcodes");
+            if (errcodes == null) {
+                logger.info("none errcodes field in: " + path);
+                return;
+            }
+
+            String fileName = null;
+            int i = path.lastIndexOf("/");
+            if (i > -1) {
+                fileName = path.substring(i + 1);
+            } else {
+                fileName = path;
+            }
+            i = fileName.indexOf("-errorcode-");
+            String localeSrc = fileName.substring(i + 11, fileName.lastIndexOf("."));
+            if (localeSrc.isEmpty()) {
+                logger.info("parse errorcode file failed: locale is null");
+                return;
+            }
+
+            String[] ss = localeSrc.replace("-", "_").split("_");
+            String tempLocale = null;
+            if (ss.length == 1) {
+                tempLocale = new Locale(ss[0]).toString();
+            } else if (ss.length == 2) {
+                tempLocale = new Locale(ss[0], ss[1]).toString();
+            } else {
+                logger.info("parse i18n file failed: locale is error \"" + localeSrc + "\"");
+                return;
+            }
+            String locale = tempLocale;
+            errcodes.forEach(errorcode -> {
+                Map<String, String> errorConfig = (Map<String, String>) errorcode;
+                Integer code = Integer.valueOf(errorConfig.get("code"));
+                String level = errorConfig.get("level");
+                String label = errorConfig.get("label");
+
+                ErrorItemImpl errorItem = errorItems.get(Integer.valueOf(code));
+                if (errorItem == null) {
+                    errorItem = new ErrorItemImpl();
+                    errorItem.errorCode = code.intValue();
+                    errorItem.level = ErrorCodeLevelUtil.transfer2Int(level);
+                    errorItems.put(code, errorItem);
+                }
+                errorItem.addLabel(locale, label);
+            });
+        });
+
+        errorItems.forEach((code, errorItem) -> {
+            errorItem.unmodifiable();
+        });
+        this.errorItems = Collections.unmodifiableMap(errorItems);
+    }
+
+
+    static DefaultErrorCodeI18n getInstance() {
+        if (singleton == null) {
+            lock.lock();
+            try {
+                if (singleton == null) {
+                    singleton = new DefaultErrorCodeI18n();
+                }
+            } finally {
+                lock.unlock();
+            }
+        }
+        return singleton;
+    }
+
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see com.zte.ums.zenap.i18n.ErrorCodeI18n#getErrorItem(int)
+     */
+    @Override
+    public Optional<ErrorItem> getErrorItem(int errorCode) {
+        return Optional.ofNullable(errorItems.get(Integer.valueOf(errorCode)));
+    }
+
+
+    public static class ErrorItemImpl implements ErrorItem {
+
+        private int errorCode;
+
+        private int level;
+
+        private Map<String, String> labels = new HashMap<String, String>();
+
+        private String jsonString = null;
+
+        @Override
+        public int getErrorCode() {
+            return errorCode;
+        }
+
+        @Override
+        public int getLevel() {
+            return level;
+        }
+
+        public Map<String, String> getLabels() {
+            return labels;
+        }
+
+        private void unmodifiable() {
+            if (labels != null) {
+                labels = Collections.unmodifiableMap(labels);
+            }
+        }
+
+        private synchronized void addLabel(String locale, String label) {
+            labels.put(locale, label);
+        }
+
+        @Override
+        public String getLabel(Locale theLocale) {
+            if (theLocale == null) {
+                return null;
+            }
+            return labels.get(I18nLocaleTransfer.transfer(theLocale, labels.keySet()));
+        }
+
+        @Override
+        public String getCanonicalLabels(int errorCode) {
+            String jsonString = this.jsonString;
+            if (jsonString == null) {
+                ErrorItem2 errorItem2 = new ErrorItem2();
+                errorItem2.setErrorCode(this.errorCode);
+                errorItem2.setLevel(ErrorCodeLevelUtil.transfer2String(this.errorCode));
+                errorItem2.setErrlabels(labels);
+                try {
+                    jsonString = I18nJsonUtil.getInstance().writeToJson(errorItem2);
+                } catch (Exception e) {
+                    logger.info("getCanonicalLabels failed from with param errorCode " + errorCode
+                            + " and this errorCode " + this.errorCode, e);
+                    return null;
+                }
+                this.jsonString = jsonString;
+            }
+            return jsonString;
+        }
+
+    }
+
+    protected static class ErrorItem2 {
+
+        private int errorCode;
+
+        private String level;
+
+        private Map<String, String> errlabels;
+
+        public ErrorItem2() {
+
+        }
+
+        public int getErrorCode() {
+            return errorCode;
+        }
+
+        public void setErrorCode(int errorCode) {
+            this.errorCode = errorCode;
+        }
+
+        public String getLevel() {
+            return level;
+        }
+
+        public void setLevel(String level) {
+            this.level = level;
+        }
+
+        public Map<String, String> getErrlabels() {
+            return errlabels;
+        }
+
+        public void setErrlabels(Map<String, String> errlabels) {
+            this.errlabels = errlabels;
+        }
+    }
+
+    protected static class ErrorCodeLevelUtil {
+
+        public static final int ERROR_LEVEL = javax.swing.JOptionPane.ERROR_MESSAGE;
+
+        public static final int WARN_LEVEL = javax.swing.JOptionPane.WARNING_MESSAGE;
+
+        public static final int INFO_LEVEL = javax.swing.JOptionPane.INFORMATION_MESSAGE;
+
+        protected static String transfer2String(int errorCode) {
+            switch (errorCode) {
+                case ERROR_LEVEL:
+                    return "ERROR";
+                case INFO_LEVEL:
+                    return "INFO";
+                case WARN_LEVEL:
+                    return "WARN";
+            }
+            return null;
+        }
+
+        protected static int transfer2Int(String level) {
+            switch (level) {
+                case "ERROR":
+                    return ERROR_LEVEL;
+                case "INFO":
+                    return INFO_LEVEL;
+                case "WARN":
+                    return WARN_LEVEL;
+            }
+            return -1;
+        }
+
+    }
+
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/DefaultI18nService.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/DefaultI18nService.java
new file mode 100644 (file)
index 0000000..820478c
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Optional;
+import javax.inject.Inject;
+import org.jvnet.hk2.annotations.Service;
+import org.openo.baseservice.i18n.ErrorCodeI18n.ErrorItem;
+
+@Service
+public final class DefaultI18nService implements I18nService {
+
+    /**
+     * Get the corresponding examples of international documents (all languages), <br>
+     *
+     * for the above example topology (for example, the Chinese definition: topo-i18n-zh-CN.json, English definition
+     * Topo -i18n-en-US.json), into the reference into the "TOPO" can be <br>
+     *
+     * (i.e. except "-i18n-*.json" after the exact match).
+     *
+     * @param i18nFilePrefix International file prefix (-i18n-*.json front part)
+     * @return Optional<I18n>
+     */
+    public Optional<I18n> getI18n(String i18nFilePrefix) {
+        return I18nContainer.getInstance().getI18n(i18nFilePrefix);
+    }
+
+    /**
+     * Gets the corresponding error item based on the error code (including the error description information for all
+     * languages)
+     *
+     * @param errorCode
+     * @return Optional<ErrorItem>
+     */
+    public Optional<ErrorItem> getErrorItem(int errorCode) {
+        return ErrorCodeI18n.getInstance().getErrorItem(errorCode);
+    }
+
+    @Inject
+    public void setObjectMapper(ObjectMapper objectMapper) {
+        I18nJsonUtil.getInstance(objectMapper);
+    }
+
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/ErrorCodeException.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/ErrorCodeException.java
new file mode 100644 (file)
index 0000000..fb470ab
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+public class ErrorCodeException extends Exception {
+
+    private static final long serialVersionUID = 5522808473663280894L;
+
+    private int errorCode;
+
+    /**
+     * Error definition placeholder replacement
+     */
+    private String[] arguments;
+
+    /**
+     * According to the original exception, error code, debug print information and construct a new anomaly placeholder
+     *
+     * @param source
+     * @param errorCode
+     * @param debugMessage
+     * @param arguments
+     */
+    public ErrorCodeException(Throwable source, int errorCode, String debugMessage, String[] arguments) {
+        super(debugMessage, source);
+
+        this.errorCode = errorCode;
+
+        this.arguments = arguments;
+    }
+
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    public String[] getArguments() {
+        return arguments;
+    }
+
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/ErrorCodeI18n.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/ErrorCodeI18n.java
new file mode 100644 (file)
index 0000000..39738b5
--- /dev/null
@@ -0,0 +1,151 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import org.openo.baseservice.i18n.DefaultErrorCodeI18n.ErrorCodeLevelUtil;
+import org.openo.baseservice.i18n.DefaultErrorCodeI18n.ErrorItem2;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+public interface ErrorCodeI18n {
+
+  static final Logger logger = LoggerFactory.getLogger(ErrorCodeI18n.class);
+
+  /**
+   * Access to the internationalization of the error code examples, scanning the process of all
+   * classes load path, loading all the *-errorcode-*.json files, and load all the international
+   * language information
+   * 
+   * @return
+   */
+  static ErrorCodeI18n getInstance() {
+    return DefaultErrorCodeI18n.getInstance();
+  }
+
+  /**
+   * Gets the corresponding error item based on the error code (including the error description
+   * information for all languages)
+   *
+   * @param errorCode
+   * @return Optional<ErrorItem>
+   */
+  public Optional<ErrorItem> getErrorItem(int errorCode);
+
+  public static interface ErrorItem {
+
+    public int getErrorCode();
+
+    public int getLevel();
+
+    public Map<String, String> getLabels();
+
+    public String getLabel(Locale theLocale);
+
+    /**
+     * All language error information description of assembly. <br>
+     * 
+     * some modules to store all the error information description or transfer, and finally the time
+     * to choose the appropriate value according to the locale presentation. <br>
+     * 
+     * it is not necessary to pass the error code (code), but in order to take into account the
+     * subsequent scalability, so also passed, the general module does not need this information.
+     * Similar form:<br>
+     * { "code":53501, "level":"INFO", "errlabels":{"zh_CN":"拓扑定制文件无效。","en_US":"The topology
+     * customized file is invalid.","ru_RU":"Топология настроенный файл недействительно."} }
+     * 
+     * @param errorCode
+     * @return
+     */
+    public String getCanonicalLabels(int errorCode);
+
+    /**
+     * With the use of the above interface, it is possible to obtain an international string
+     * corresponding to a specific language from the combination of all error messages
+     * 
+     * @param labels Error message description string (Return value of the getCanonicalLabels
+     *        method)
+     * @param theLocale
+     * @return
+     */
+    public static String getLabelFromCanonicalLabels(String labels, Locale theLocale) {
+      if (labels == null || theLocale == null) {
+        return null;
+      }
+      try {
+        ErrorItem2 errorItem2 = I18nJsonUtil.getInstance().readFromJson(labels, ErrorItem2.class);
+        Map<String, String> errlabels = errorItem2.getErrlabels();
+        return errlabels.get(I18nLocaleTransfer.transfer(theLocale, errlabels.keySet()));
+      } catch (Exception e) {
+        logger.info(
+            "getLabelFromCanonicalLabels failed from " + labels + " with local " + theLocale, e);
+        return null;
+      }
+    }
+
+    /**
+     * With the use of the above interface, we can get the error code corresponding to the specific
+     * language from all the error information
+     * 
+     * @param labels Error message description string (Return value of the getCanonicalLabels
+     *        method)
+     * @param theLocale
+     * @return errorCode
+     */
+    public static int getErrorcodeFromCanonicalLabels(String labels, Locale theLocale) {
+      if (labels == null) {
+        return -1;
+      }
+      try {
+        ErrorItem2 errorItem2 = I18nJsonUtil.getInstance().readFromJson(labels, ErrorItem2.class);
+        return errorItem2.getErrorCode();
+      } catch (Exception e) {
+        logger.info(
+            "getErrorcodeFromCanonicalLabels failed from " + labels + " with local " + theLocale,
+            e);
+        return -1;
+      }
+    }
+
+    /**
+     * With the above interface, the error level of the corresponding string is obtained from all
+     * the error messages
+     *
+     * @param labels Error message description string (Return value of the getCanonicalLabels
+     *        method)
+     * @param theLocale
+     * @return error level
+     */
+    public static int getLevelFromCanonicalLabels(String labels, Locale theLocale) {
+      if (labels == null) {
+        return -1;
+      }
+      try {
+        ErrorItem2 errorItem2 = I18nJsonUtil.getInstance().readFromJson(labels, ErrorItem2.class);
+        return ErrorCodeLevelUtil.transfer2Int(errorItem2.getLevel());
+      } catch (Exception e) {
+        logger.info(
+            "getErrorcodeFromCanonicalLabels failed from " + labels + " with local " + theLocale,
+            e);
+        return -1;
+      }
+    }
+  }
+
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18n.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18n.java
new file mode 100644 (file)
index 0000000..ec9197b
--- /dev/null
@@ -0,0 +1,132 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+public interface I18n {
+  static final Logger logger = LoggerFactory.getLogger(I18n.class);
+
+  /**
+   * Get the corresponding examples of international documents (all languages), <br>
+   * 
+   * for the above example topology (for example, the Chinese definition: topo-i18n-zh-CN.json,
+   * English definition Topo -i18n-en-US.json), into the reference into the "TOPO" can be <br>
+   * 
+   * (i.e. except "-i18n-*.json" after the exact match).
+   * 
+   * @param i18nFilePrefix
+   * @return Optional<I18n>
+   */
+  public static Optional<I18n> getInstance(String i18nFilePrefix) {
+    return I18nContainer.getInstance().getI18n(i18nFilePrefix);
+  }
+
+  /**
+   * According to key, the internationalization of all languages is described (Map<locale,value>)
+   * 
+   * @param labelKey key
+   * @return Map<locale,value>
+   */
+  public Map<String, String> getLabelValues(String labelKey);
+
+  /**
+   * According to key, the internationalization of all languages is described
+   * 
+   * @param labelKey
+   * @param theLocale
+   * @return
+   */
+  public String getLabelValue(String labelKey, Locale theLocale);
+
+  /**
+   * According to key, the internationalization of all languages is described
+   * 
+   * @param labelKey
+   * @param theLocale
+   * @param arguments
+   * @return
+   */
+  public String getLabelValue(String labelKey, Locale theLocale, String[] arguments);
+
+  /**
+   * Replace the placeholder that is defined in the internationalization description, as shown in
+   * the following example, <br>
+   * 
+   * {0} represents first bits, which will be replaced by a specific number of days. : <br>
+   * 
+   * {"col_dir_file_time_table": "save days {0} days"}
+   * 
+   * @param labelKey
+   * @param arguments
+   * @return Map<locale,value>
+   */
+  public Map<String, String> getLabelValues(String labelKey, String[] arguments);
+
+  /**
+   * According to the key to get all the international description of the language, and the results
+   * will be combined into a Json string, used in the log module scene, <br>
+   * 
+   * it is necessary to store all of the international information or transfer, and finally show the
+   * time according to locale to choose the appropriate value. <br>
+   * 
+   * (here in order to form similar to read, plus a newline) <br>
+   * {"zh_CN":"统一公共应用","en_US":" Unified common application ","ru_RU":"Единый общий приложений"}
+   * 
+   * @param labelKey key
+   * @return
+   */
+  public String getCanonicalLabelValues(String labelKey);
+
+  /**
+   * With the use of getCanonicalLabelValues interface, from all the international description of
+   * the combination of string and specific language corresponding to the international string. The
+   * return value of the getCanonicalLabelValues method
+   * 
+   * @param values
+   * @param theLocale
+   * @return value
+   */
+  public static String getValuefromCanonicalValues(String values, Locale theLocale) {
+    try {
+      @SuppressWarnings("unchecked")
+      HashMap<String, String> map = I18nJsonUtil.getInstance().readFromJson(values, HashMap.class);
+
+      return map.get(I18nLocaleTransfer.transfer(theLocale, map.keySet()));
+    } catch (Exception e) {
+      logger.error("get i18n value failed by locale:" + theLocale + " from " + values, e);
+      return null;
+    }
+  }
+
+  /**
+   * According to the value to find the corresponding key, such as a module in accordance with
+   * international content filtering, search, database storage is key, then the front pass query is
+   * a kind of language corresponding to the value, to get the corresponding international key to
+   * the database query.
+   *
+   * @param value
+   * @return
+   */
+  public String getKeyFromValue(String value);
+
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nContainer.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nContainer.java
new file mode 100644 (file)
index 0000000..95ae105
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+
+final class I18nContainer {
+
+  private static Logger logger = LoggerFactory.getLogger(I18nContainer.class);
+
+  private Map<String, I18n> i18ns;
+
+  private I18nContainer() {
+    init();
+  }
+
+
+  private void init() {
+    Map<String, Map<String, I18nItem>> i18nTemps = generateI18ns();
+
+    i18ns = new HashMap<String, I18n>();
+    for (Entry<String, Map<String, I18nItem>> entry : i18nTemps.entrySet()) {
+      String name = entry.getKey();
+      Map<String, I18nItem> items = entry.getValue();
+      for (Entry<String, I18nItem> i18nItemEntry : items.entrySet()) {
+        i18nItemEntry.getValue().unmodifiable();
+      }
+
+      I18n i18n = new I18nImpl(name, items);
+      i18ns.put(name, i18n);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private Map<String, Map<String, I18nItem>> generateI18ns() {
+    Map<String, Map<String, I18nItem>> i18nTemps = new HashMap<String, Map<String, I18nItem>>();
+
+    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+    JsonResourceScanner.findI18nPaths().forEach((path) -> {
+      HashMap<String, String> fileValues = null;
+      try (InputStream ins = systemClassLoader.getResourceAsStream(path)) {
+        fileValues = I18nJsonUtil.getInstance().readFromJson(ins, HashMap.class);
+        logger.info("load i18n file success: " + path);
+      } catch (IOException ex) {
+        logger.info("load i18n file failed: " + path);
+        logger.info("load i18n file failed: " + systemClassLoader.getResource(path).toString(), ex);
+        return;
+      }
+
+      if (!validateI18nFileValues(fileValues, path)) {
+        return;
+      }
+
+      String fileName = null;
+      int i = path.lastIndexOf("/");
+      if (i > -1) {
+        fileName = path.substring(i + 1);
+      } else {
+        fileName = path;
+      }
+      i = fileName.indexOf("-i18n-");
+      String name = fileName.substring(0, i);
+      String localeSrc = fileName.substring(i + 6, fileName.lastIndexOf("."));
+      if (name.isEmpty()) {
+        logger.info("parse i18n file failed: name is null");
+        return;
+      } else if (localeSrc.isEmpty()) {
+        logger.info("parse i18n file failed: locale is null");
+        return;
+      }
+
+      String[] ss = localeSrc.replace("-", "_").split("_");
+      String locale = null;
+      if (ss.length == 1) {
+        locale = new Locale(ss[0]).toString();
+      } else if (ss.length == 2) {
+        locale = new Locale(ss[0], ss[1]).toString();
+      } else {
+        logger.info("parse i18n file failed: locale is error \"" + localeSrc + "\"");
+        return;
+      }
+
+      Map<String, I18nItem> i18nItems = i18nTemps.get(name);
+      if (i18nItems == null) {
+        i18nItems = new HashMap<String, I18nItem>();
+        i18nTemps.put(name, i18nItems);
+      }
+
+      for (Entry<String, String> entry : fileValues.entrySet()) {
+        String label = entry.getKey();
+
+        I18nItem i18nItem = i18nItems.get(label);
+        if (i18nItem == null) {
+          i18nItem = new I18nItem(label);
+          i18nItems.put(label, i18nItem);
+        }
+
+        i18nItem.addValue(locale, entry.getValue());
+      }
+    });
+    return i18nTemps;
+  }
+
+  private boolean validateI18nFileValues(HashMap<String, String> fileValues, String path) {
+    for (Entry<String, String> entry : fileValues.entrySet()) {
+      if (entry.getValue() != null && !String.class.isInstance(entry.getValue())) {
+        logger.info("parse i18n file failed: " + path + " field's[" + entry.getKey()
+            + "] value is not string type");
+        return false;
+      }
+    }
+    return true;
+  }
+
+  protected static I18nContainer getInstance() {
+    return I18nContainerSingleton.singleton;
+  }
+
+  Optional<I18n> getI18n(String name) {
+    return Optional.ofNullable(this.i18ns.get(name));
+  }
+
+  static class I18nContainerSingleton {
+    private static final I18nContainer singleton = new I18nContainer();
+  }
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nImpl.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nImpl.java
new file mode 100644 (file)
index 0000000..bda6f2d
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class I18nImpl implements I18n {
+  private static Logger logger = LoggerFactory.getLogger(I18nImpl.class);
+
+  private String name;
+
+  private Map<String, I18nItem> items;
+
+  private Map<String, String> keyToValueMap;
+
+  private Map<String, String> valueToKeyMap;
+
+
+  public I18nImpl(String name, Map<String, I18nItem> items) {
+    this.name = name;
+    this.items = Collections.unmodifiableMap(items);
+
+    keyToValueMap = new HashMap<>(items.size());
+    valueToKeyMap = new HashMap<>(items.size() * 3);
+
+    try {
+      for (Entry<String, I18nItem> entry : items.entrySet()) {
+        String key = entry.getKey();
+        I18nItem item = entry.getValue();
+        String value = I18nJsonUtil.getInstance().writeToJson(item.getValues());
+
+        keyToValueMap.put(key, value);
+        for (Entry<String, String> valueEntry : item.getValues().entrySet()) {
+          valueToKeyMap.put(valueEntry.getValue(), key);
+        }
+      }
+    } catch (Exception e) {
+      logger.error("new I18nImpl failed:" + name, e);
+    }
+
+    keyToValueMap = Collections.unmodifiableMap(keyToValueMap);
+    valueToKeyMap = Collections.unmodifiableMap(valueToKeyMap);
+  }
+
+  @Override
+  public Map<String, String> getLabelValues(String labelKey) {
+    I18nItem item = items.get(labelKey);
+    if (item != null) {
+      return item.getValues();
+    }
+    return null;
+  }
+
+  @Override
+  public String getLabelValue(String labelKey, Locale theLocale) {
+    I18nItem item = items.get(labelKey);
+    if (item != null) {
+      Map<String, String> values = item.getValues();
+      return values.get(I18nLocaleTransfer.transfer(theLocale, values.keySet()));
+    }
+    return null;
+  }
+
+  @Override
+  public String getLabelValue(String labelKey, Locale theLocale, String[] arguments) {
+    I18nItem item = items.get(labelKey);
+    if (item != null) {
+      Map<String, String> values = item.getValues();
+      String value = values.get(I18nLocaleTransfer.transfer(theLocale, values.keySet()));
+      return replaceArguments(value, arguments);
+    }
+    return null;
+  }
+
+  @Override
+  public Map<String, String> getLabelValues(String labelKey, String[] arguments) {
+    I18nItem item = items.get(labelKey);
+    if (item != null) {
+      Map<String, String> map = new HashMap<String, String>();
+      for (Entry<String, String> entry : item.getValues().entrySet()) {
+        String value = entry.getValue();
+        map.put(entry.getKey(), replaceArguments(value, arguments));
+      }
+      return map;
+    }
+    return null;
+  }
+
+  @Override
+  public String getCanonicalLabelValues(String labelKey) {
+    return keyToValueMap.get(labelKey);
+  }
+
+  @Override
+  public String getKeyFromValue(String aValue) {
+    return valueToKeyMap.get(aValue);
+  }
+
+  private String replaceArguments(String value, String[] arguments) {
+    if (value == null) {
+      return null;
+    }
+    if (arguments != null) {
+      int i = 0;
+      for (String argument : arguments) {
+        if (argument == null) {
+          value = value.replaceAll("\\{\\s*" + i + "\\s*\\}", "");
+        } else {
+          value = value.replaceAll("\\{\\s*" + i + "\\s*\\}", argument);
+        }
+        i++;
+      }
+    }
+    return value.replaceAll("\\{\\s*\\d+\\s*\\}", "");
+  }
+
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nItem.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nItem.java
new file mode 100644 (file)
index 0000000..1aaaf6f
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class I18nItem {
+
+  private String lable;
+
+  private Map<String, String> values;
+
+  public I18nItem(String lable) {
+    this.lable = lable;
+    values = new HashMap<String, String>();
+  }
+
+  public I18nItem(String lable, Map<String, String> values) {
+    this.lable = lable;
+    this.values = values;
+  }
+
+  public String getLable() {
+    return lable;
+  }
+
+  public Map<String, String> getValues() {
+    return values;
+  }
+
+  public void addValue(String locale, String value) {
+    values.put(locale, value);
+  }
+
+  public void unmodifiable() {
+    values = Collections.unmodifiableMap(values);
+  }
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nJsonUtil.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nJsonUtil.java
new file mode 100644 (file)
index 0000000..e3746dc
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class I18nJsonUtil {
+
+    private static I18nJsonUtil util;
+    private static Lock lock = new ReentrantLock();
+    private ObjectMapper objectMapper;
+
+    public I18nJsonUtil(ObjectMapper objectMapper) {
+        this.objectMapper = objectMapper;
+    }
+
+    <T extends Object> T readFromJson(InputStream ins, Class<T> clazz)
+        throws JsonParseException, JsonMappingException, IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] bs = new byte[1024 * 10];
+        int length = -1;
+        while ((length = ins.read(bs)) > 0) {
+            baos.write(bs, 0, length);
+        }
+        bs = baos.toByteArray();
+
+        byte[] ubs = null;
+        if (bs.length > 3) {
+            // 删除bom头 -17, -69, -65
+            if (bs[0] == -17 && bs[1] == -69 && bs[2] == -65) {
+                ubs = new byte[bs.length - 3];
+                System.arraycopy(bs, 3, ubs, 0, ubs.length);
+            }
+        }
+        if (ubs == null) {
+            ubs = bs;
+        }
+        return objectMapper.readValue(ubs, clazz);
+    }
+
+    <T extends Object> T readFromJson(String str, Class<T> clazz)
+        throws JsonParseException, JsonMappingException, IOException {
+        return objectMapper.readValue(str, clazz);
+    }
+
+    String writeToJson(Object obj) throws JsonProcessingException {
+        return objectMapper.writeValueAsString(obj);
+    }
+
+    static I18nJsonUtil getInstance(ObjectMapper objectMapper) {
+        if (util == null) {
+            lock.lock();
+            try {
+                if (util == null) {
+                    if (objectMapper == null) {
+                        objectMapper = new ObjectMapper();
+                    }
+                    util = new I18nJsonUtil(objectMapper);
+                }
+            } finally {
+                lock.unlock();
+            }
+        }
+        return util;
+    }
+
+    static I18nJsonUtil getInstance() {
+        return getInstance(null);
+    }
+}
+
+
+/**
+ * 国际化转换工具
+ *
+ * @author 10163976
+ */
+class I18nLocaleTransfer {
+
+    private static Logger LOG = LoggerFactory.getLogger(I18nLocaleTransfer.class);
+
+    /**
+     * 方言转换<br> 如果存在直接返回<br> 如果不存在,则获取语言进行模糊匹配,未匹配上则返回默认方言<br>
+     *
+     * @param theLocale 待转换方言
+     * @param locales 存在的方言
+     * @return 转换后的方言
+     */
+    public static String transfer(Locale theLocale, Set<String> locales) {
+        if (locales == null || locales.isEmpty()) {
+            LOG.debug("locales is NULL or empty");
+            return null;
+        }
+        if (theLocale == null) {
+            String result = fetchDefault(locales);
+            LOG.debug("transfer NULL --> " + result + " in " + locales);
+            return result;
+        }
+        String locale = theLocale.toString();
+        if (locale.isEmpty()) {
+            String result = fetchDefault(locales);
+            LOG.debug("transfer EMPTY --> " + result + " in " + locales);
+            return result;
+        }
+        // 精确匹配
+        if (locales.contains(locale)) {
+            return locale;
+        }
+
+        // 根据语言模糊匹配
+        String language = theLocale.getLanguage();
+        if (locales.contains(language)) {
+            LOG.debug("transfer " + locale + " --> " + language + " in " + locales);
+            return language;
+        }
+
+        language = language + "_";
+        for (String temp : locales) {
+            if (temp.startsWith(language)) {
+                LOG.debug("transfer " + locale + " --> " + temp + " in " + locales);
+                return temp;
+            }
+        }
+        String result = fetchDefault(locales);
+        LOG.debug("transfer " + locale + " --> " + result + " in " + locales);
+        return result;
+    }
+
+    /**
+     * 返回默认方言,优先级为en,en_US,zh,zh_CN,如果都不存在,则随机返回一个
+     */
+    private static String fetchDefault(Set<String> locales) {
+        if (locales.contains("en")) {
+            return "en";
+        } else if (locales.contains("en_US")) {
+            return "en_US";
+        }
+        if (locales.contains("zh")) {
+            return "zh";
+        } else if (locales.contains("zh_CN")) {
+            return "zh_CN";
+        }
+        return locales.iterator().next();
+    }
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nService.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/I18nService.java
new file mode 100644 (file)
index 0000000..a643356
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+
+import java.util.Optional;
+import org.jvnet.hk2.annotations.Contract;
+import org.openo.baseservice.i18n.ErrorCodeI18n.ErrorItem;
+
+@Contract
+public interface I18nService {
+
+    /**
+     * Get the corresponding examples of international documents (all languages), <br> for the above
+     * example topology (for example, the Chinese definition: topo-i18n-zh-CN.json, English
+     * definition Topo -i18n-en-US.json), into the reference into the "TOPO" can be <br> (i.e.
+     * except "-i18n-*.json" after the exact match).
+     *
+     * @return Optional<I18n>
+     */
+    public Optional<I18n> getI18n(String i18nFilePrefix);
+
+    public Optional<ErrorItem> getErrorItem(int errorCode);
+
+}
diff --git a/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/JsonResourceScanner.java b/baseservice-i18n/src/main/java/org/openo/baseservice/i18n/JsonResourceScanner.java
new file mode 100644 (file)
index 0000000..9f5ef3a
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2017 ZTE Corporation.
+ *
+ * Licensed 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.openo.baseservice.i18n;
+
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+final class JsonResourceScanner {
+  private static final org.slf4j.Logger LOG =
+      org.slf4j.LoggerFactory.getLogger(JsonResourceScanner.class);
+  private static final Pattern PATTERN_OF_I18N_FILE_NAME =
+      Pattern.compile(".*?\\-i18n\\-.*?\\.json");
+  private static final Pattern PATTERN_OF_ERROR_CODE_FILE_NAME =
+      Pattern.compile(".*?\\-errorcode\\-.*?\\.json");
+
+  private static Collection<String> findFromClassPath(Pattern pattern) {
+    ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
+    Collection<URL> urls = ClasspathHelper.forJavaClassPath();
+
+    for (Iterator<URL> iter = urls.iterator(); iter.hasNext();) {
+      URL url = iter.next();
+      boolean exist = false;
+      try {
+        exist = new File(url.getFile()).exists();
+        if (!exist) {
+          LOG.info("class path url ignored for not exists: " + url.toString());
+        }
+      } catch (Exception e) {
+        LOG.info("class path url ignored for exception: " + url.toString(), e);
+        exist = false;
+      }
+      if (!exist) {
+        iter.remove();
+      }
+    }
+    for (URL url : urls) {
+      LOG.info("class path url:" + url.toString());
+    }
+    configurationBuilder.addUrls(urls);
+    configurationBuilder.setScanners(new ResourcesScanner());
+    configurationBuilder.useParallelExecutor();
+    Reflections reflections = new Reflections(configurationBuilder);
+    Set<String> results = reflections.getResources(pattern);
+    if (results == null) {
+      return Collections.emptySet();
+    } else {
+      return results;
+    }
+  }
+
+  static Collection<String> findI18nPaths() {
+    return findFromClassPath(PATTERN_OF_I18N_FILE_NAME);
+  }
+
+  static Collection<String> findErrorCodePaths() {
+    return findFromClassPath(PATTERN_OF_ERROR_CODE_FILE_NAME);
+  }
+}