/* * RapidMiner * * Copyright (C) 2001-2014 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.tour; import java.awt.Font; import java.awt.FontFormatException; import java.awt.GraphicsEnvironment; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Properties; import java.util.logging.Level; import com.rapidminer.repository.RepositoryException; import com.rapidminer.tools.FileSystemService; import com.rapidminer.tools.LogService; import com.rapidminer.tools.Tools; /** * This Class manages whether a Tour is new, started or finishid. Also it remembers the * number of the highest Step the user made in a Tour and whether the user wants to be asked again * by starting RapidMiner if he want to execute a Tour. * * @author Thilo Kamradt */ public class TourManager { private static String TOUR_PROPERTIES = "tours.properties"; //log messages private final String logPath = "com.rapidminer.gui.tour.TourManager."; private final String NO_FONT = logPath + "font_not_loaded"; private final String NOT_SAVED = logPath + "could_not_save"; private final String NOT_STARTED = logPath + "could_not_start"; private final String NOT_FOUND = logPath + "not_found"; private final String NO_KEY = logPath + "key_not_found"; private final String NO_INDEX = logPath +"index_not_found"; private static TourManager INSTANCE; private Properties properties; private HashMap<String, Class<? extends IntroductoryTour>> tours; private ArrayList<String> indexList; private TourManager() { load(); tours = new HashMap<String, Class<? extends IntroductoryTour>>(); indexList = new ArrayList<String>(); // try to load a comic Font try { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, Tools.getResourceInputStream("/fonts/AlterEgoBB.ttf"))); } catch (IOException e) { LogService.getRoot().log(Level.WARNING, NO_FONT); } catch (FontFormatException e1) { LogService.getRoot().log(Level.WARNING, NO_FONT); } catch (RepositoryException e2) { LogService.getRoot().log(Level.WARNING, NO_FONT); } // registers tours from Rapid-i self this.registerTour("RapidMiner", RapidMinerTour.class); } /** * Method to get the instance of the TourManager. Should be called instead of Constructor ! * @return returns the TourManager */ public static synchronized TourManager getInstance() { if (INSTANCE == null) { INSTANCE = new TourManager(); } return INSTANCE; } private void load() { this.properties = new Properties(); File file = FileSystemService.getUserConfigFile(TOUR_PROPERTIES); try { file.createNewFile(); properties.load(new FileInputStream(file)); } catch (FileNotFoundException e) { LogService.getRoot().log(Level.INFO, NOT_FOUND); } catch (IOException e) { LogService.getRoot().log(Level.INFO, NOT_FOUND); } } private boolean save() { File file = FileSystemService.getUserConfigFile(TOUR_PROPERTIES); try { properties.store(new FileOutputStream(file), "RapidMiner Datafiles"); return true; } catch (FileNotFoundException e) { LogService.getRoot().log(Level.WARNING, NOT_SAVED); return false; } catch (IOException e) { LogService.getRoot().log(Level.WARNING, NOT_SAVED); return false; } } /** * changes the Property-file-entry to the given state * @param tourKey key/name of the Tour * @param state {@link TourState} to write to the file */ public void setTourState(String tourKey, TourState state) { if (state == TourState.NEVER_ASK) { properties.setProperty(tourKey + ".ask", state.toString()); save(); } else { String currentState = properties.getProperty(tourKey); if(currentState == null) { properties.setProperty(tourKey, state.toString()); save(); } else if(!(TourState.valueOf(currentState) == TourState.COMPLETED)) { properties.setProperty(tourKey, state.toString()); save(); } } } /** * writes the progress of the Tour to the property-file * @param tourKey key/name of the Tour * @param step index of the current {@link Step} of the Tour (counting started with 1). */ public void setTourProgress(String tourKey, int step, int totalLength) { int stateBefore = Integer.parseInt(properties.getProperty(tourKey + ".progress", "" + 0)); if (stateBefore < step) { properties.setProperty(tourKey + ".progress", "" + step); properties.setProperty(tourKey + ".length", "" + totalLength); save(); } } /** * @param tourKey key / name of the Tour * @return returns the {@link TourState} of the Tour with the given key or TourState.NEW_ONE if there was no entry in the Property-file. */ public TourState getTourState(String tourKey) { String stateKey = properties.getProperty(tourKey); if (stateKey == null) { setTourState(tourKey, TourState.NEW_ONE); return TourState.NEW_ONE; } else { return TourState.valueOf(stateKey); } } /** * @param tourKey key/name of the Tour * @return true if the user wants to be asked again and false otherwise */ public boolean getAskState(String tourKey) { if (properties.getProperty(tourKey + ".ask", null) == null) { return true; } else { return false; } } /** * @param tourKey name/key of the Tour. * @return returns the maximum number of Steps the user has begun * (e.g. if the user once made 5 Steps and another time he made 15 Steps this Method returns 15) */ public int getProgress(String tourKey) { return Integer.parseInt(properties.getProperty(tourKey + ".progress", "" + 0)); } /** * @return returns the progress in percent rounded to an Integer. */ public int getProgressInPercent(String tourKey) { int length = this.getTourLength(tourKey); if(length == 0) return 0; return (this.getProgress(tourKey)*100) / length; } /** * @return returns the length of the Tour or 0 if the Tour wasn't even started until now. */ public int getTourLength(String tourKey) { return Integer.parseInt(properties.getProperty(tourKey+".length", ""+0)); } /** * It's necessary to call this method in by the start of RapidMiner, to show your Tour in the Selection-Dialog for Tours. * @param tourKey name/key of your Tour * @param tourClass Class-object of your Tour */ public void registerTour(String tourKey, Class<? extends IntroductoryTour> tourClass) { tours.put(tourKey, tourClass); indexList.add(tourKey); } /** * @return returns an Array of the keys from all registered Tours */ public String[] getTourkeys() { return tours.keySet().toArray(new String[] {}); } /** * * @return returns the number of registered Tours. */ public int size() { return tours.size(); } /** * @param index index of a Tour must be smaller than the value of TourManager.size(). * @return return returns an instance of a subclass from {@link IntroductoryTour} which got the index by registration. */ public IntroductoryTour get(int index) { IntroductoryTour tour = null; try { tour = tours.get(indexList.get(index)).newInstance(); } catch (InstantiationException e) { LogService.getRoot().log(Level.WARNING, NO_INDEX, new Object[] {index}); throw new IllegalArgumentException(); } catch (IllegalAccessException e) { LogService.getRoot().log(Level.WARNING, NO_INDEX, new Object[] {index}); throw new IllegalArgumentException(); } return tour; } /** * @param tourKey key/name of the Tour * @return returns an instance of a subclass of {@link IntroductoryTour} with the given key */ public IntroductoryTour get(String tourKey) { IntroductoryTour tour = null; Class<? extends IntroductoryTour> tourClass = tours.get(tourKey); try { tour = tourClass.newInstance(); } catch (InstantiationException e) { LogService.getRoot().log(Level.WARNING, NO_KEY, new Object[] {tourKey}); throw new IllegalArgumentException(); } catch (IllegalAccessException e) { LogService.getRoot().log(Level.WARNING, NO_KEY, new Object[] {tourKey}); throw new IllegalArgumentException(); } return tour; } /** * Starts the Tour with the given key and returns the running object * @param tourKey key/name of the Tour * @return returns the running object or throws a RuntimeException if the key doesn't match any tour. */ public IntroductoryTour startTour(String tourKey) { IntroductoryTour tour = null; Class<? extends IntroductoryTour> tourClass = tours.get(tourKey); try { tour = tourClass.newInstance(); tour.startTour(); } catch (InstantiationException e) { LogService.getRoot().log(Level.WARNING, NOT_STARTED, new Object[] {tourKey}); throw new IllegalArgumentException(); } catch (IllegalAccessException e) { LogService.getRoot().log(Level.WARNING, NOT_STARTED, new Object[] {tourKey}); throw new IllegalArgumentException(); } return tour; } }