/* * Copyright (c) 2018. Developed by Hedgecode. * * 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.hedgecode.chess.uci; import java.io.File; import java.io.FilenameFilter; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hedgecode.chess.uci.annotation.Command; import org.hedgecode.chess.uci.annotation.CommandDirection; /** * * * @author Dmitry Samoshin aka gotty */ public class CommandDescriptor { private static final char PKG_SEPARATOR = '.'; private static final char DIR_SEPARATOR = '/'; private static final String CLASS_FILE_SUFFIX = ".class"; private static final String PACKAGE_IS_NOT_EXISTS = "The package '%s' is not exists."; private Map commandsTo = new HashMap<>(); private Map commandsFrom = new HashMap<>(); CommandDescriptor() throws Exception { initCommands(); } private void initCommands() throws Exception { initCommands( CommandDescriptor.class.getPackage().getName() ); } private void initCommands(String packageName) throws Exception { URL packageUrl = Thread.currentThread().getContextClassLoader().getResource( packageName.replace(PKG_SEPARATOR, DIR_SEPARATOR) ); if (packageUrl == null) throw new IllegalArgumentException( String.format(PACKAGE_IS_NOT_EXISTS, packageName) ); List commandClasses = findCommands( new File( packageUrl.getFile() ), packageName ); commandsTo.clear(); commandsFrom.clear(); for (Class commandClass : commandClasses) { if (UCICommand.class.isAssignableFrom(commandClass)) { UCICommand uciCommand = (UCICommand) commandClass.newInstance(); Command command = (Command) commandClass.getAnnotation(Command.class); switch (command.direction()) { case TO_ENGINE: commandsTo.put( command.name(), uciCommand ); break; case FROM_ENGINE: commandsFrom.put( command.name(), uciCommand ); break; } } } } private List findCommands(File dir, String packageName) throws Exception { List commands = new ArrayList<>(); File[] classFiles = dir.listFiles( new FilenameFilter() { public boolean accept(File file, String name) { return name.endsWith(CLASS_FILE_SUFFIX); } } ); if (classFiles != null) { for (File classFile : classFiles) { String className = packageName + PKG_SEPARATOR + classFile.getName(); int endIndex = className.length() - CLASS_FILE_SUFFIX.length(); className = className.substring(0, endIndex); Class clazz = Class.forName(className); if (clazz.isAnnotationPresent(Command.class)) { commands.add(clazz); } } } File[] subDirs = dir.listFiles( new FilenameFilter() { public boolean accept(File file, String name) { return file.isDirectory(); } } ); if (subDirs != null) { for (File subDir : subDirs) { commands.addAll( findCommands( subDir, packageName + PKG_SEPARATOR + subDir.getName() ) ); } } return commands; } public UCICommand getCommand(String name, CommandDirection direction) { switch (direction) { case TO_ENGINE: return commandsTo.get(name); case FROM_ENGINE: return commandsFrom.get(name); } return null; } public static void main(String[] arg) throws Exception { CommandDescriptor cd = new CommandDescriptor(); //cd.initCommands(); UCICommand command; command = cd.getCommand("uci", CommandDirection.TO_ENGINE); System.out.println(command); command = cd.getCommand("debug", CommandDirection.TO_ENGINE); System.out.println(command); command = cd.getCommand("test", CommandDirection.TO_ENGINE); System.out.println(command); } }