001/**
002 * Copyright (C) 2007-2011, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 * 
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 *
019 */
020package org.dllearner.cli;
021
022import org.apache.log4j.Level;
023import org.dllearner.algorithms.decisiontrees.dsttdt.DSTTDTClassifier;
024import org.dllearner.algorithms.decisiontrees.refinementoperators.DLTreesRefinementOperator;
025import org.dllearner.algorithms.decisiontrees.tdt.TDTClassifier;
026import org.dllearner.configuration.IConfiguration;
027import org.dllearner.configuration.spring.ApplicationContextBuilder;
028import org.dllearner.configuration.spring.DefaultApplicationContextBuilder;
029import org.dllearner.confparser.ConfParserConfiguration;
030import org.dllearner.confparser.ParseException;
031import org.dllearner.core.*;
032import org.dllearner.core.config.ConfigOption;
033import org.dllearner.learningproblems.PosNegLP;
034import org.semanticweb.owlapi.model.OWLClass;
035import org.semanticweb.owlapi.model.OWLObjectProperty;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038import org.springframework.context.ApplicationContext;
039import org.springframework.core.io.FileSystemResource;
040import org.springframework.core.io.Resource;
041
042import java.io.File;
043import java.io.FileOutputStream;
044import java.io.IOException;
045import java.io.PrintStream;
046import java.util.ArrayList;
047import java.util.List;
048import java.util.Map;
049import java.util.Map.Entry;
050
051//import org.dllearner.algorithms.qtl.QTL2;
052
053/**
054 * 
055 * New commandline interface.
056 * 
057 * @author Jens Lehmann
058 *
059 */
060@ComponentAnn(name = "Command Line Interface", version = 0, shortName = "")
061public class CLI extends CLIBase2 {
062
063        private static Logger logger = LoggerFactory.getLogger(CLI.class);
064
065        private LearningAlgorithm algorithm;
066        private KnowledgeSource knowledgeSource;
067        
068        // some CLI options
069        @ConfigOption(defaultValue = "false", description = "Run in Cross-Validation mode")
070        private boolean performCrossValidation = false;
071        @ConfigOption(defaultValue = "10", description = "Number of folds in Cross-Validation mode")
072        private int nrOfFolds = 10;
073
074        private AbstractClassExpressionLearningProblem lp;
075
076        private AbstractReasonerComponent rs;
077
078        private AbstractCELA la;
079        
080
081        public CLI() {
082                
083        }
084        
085        public CLI(File confFile) {
086                this();
087                this.confFile = confFile;
088        }
089        
090        // separate init methods, because some scripts may want to just get the application
091        // context from a conf file without actually running it
092        @Override
093        public void init() throws IOException {
094        if(context == null) {
095                    super.init();
096            
097            knowledgeSource = context.getBean(KnowledgeSource.class);
098            rs = getMainReasonerComponent();
099                la = context.getBean(AbstractCELA.class);
100                lp = context.getBean(AbstractClassExpressionLearningProblem.class);
101        }
102        }
103        
104    @Override
105    public void run() {
106        try {
107                        org.apache.log4j.Logger.getLogger("org.dllearner").setLevel(Level.toLevel(logLevel.toUpperCase()));
108                } catch (Exception e) {
109                        logger.warn("Error setting log level to " + logLevel);
110                }
111
112                rs = getMainReasonerComponent();
113                
114                
115                        if (performCrossValidation) {
116                                la = context.getBeansOfType(AbstractCELA.class).entrySet().iterator().next().getValue();
117                                
118                                PosNegLP lp = context.getBean(PosNegLP.class);
119//                              if(la instanceof QTL2){
120//                                      //new SPARQLCrossValidation((QTL2Disjunctive) la,lp,rs,nrOfFolds,false);
121//                              }
122                                if((la instanceof TDTClassifier)||(la instanceof DSTTDTClassifier) ){
123                                        
124                                        //TODO:  verify if the quality of the code can be improved
125                                        DLTreesRefinementOperator op = context.getBeansOfType(DLTreesRefinementOperator.class).entrySet().iterator().next().getValue();
126                                        ArrayList<OWLClass> concepts = new ArrayList<>(rs.getClasses());
127                                        op.setAllConcepts(concepts);
128                                        
129                                        ArrayList<OWLObjectProperty> roles = new ArrayList<>(rs.getAtomicRolesList());
130                                        op.setAllConcepts(concepts);
131                                        op.setAllRoles(roles);
132                                        op.setReasoner(getMainReasonerComponent());
133                                        
134                                        if (la instanceof TDTClassifier)
135                                            ((TDTClassifier)la).setOperator(op);
136                                        else
137                                                ((DSTTDTClassifier)la).setOperator(op);
138                                        new CrossValidation2(la,lp,rs,nrOfFolds,false);
139                                }else {
140                                        new CrossValidation2(la,lp,rs,nrOfFolds,false);
141                                }
142                        } else {
143                                if(context.getBean(AbstractLearningProblem.class) instanceof AbstractClassExpressionLearningProblem) {
144                                        lp = context.getBean(AbstractClassExpressionLearningProblem.class);
145                                } else {
146                                        
147                                }
148                                
149                                Map<String, LearningAlgorithm> learningAlgs = context.getBeansOfType(LearningAlgorithm.class);
150//                              knowledgeSource = context.getBeansOfType(Knowledge1Source.class).entrySet().iterator().next().getValue();
151                                for(Entry<String, LearningAlgorithm> entry : learningAlgs.entrySet()){
152                                        algorithm = entry.getValue();
153                                        logger.info("Running algorithm instance \"" + entry.getKey() + "\" (" + algorithm.getClass().getSimpleName() + ")");
154                                        algorithm.start();
155                                }
156                        }
157    }
158
159        /**
160         * @return the lp
161         */
162        public AbstractClassExpressionLearningProblem getLearningProblem() {
163                return lp;
164        }
165        
166        /**
167         * @return the rs
168         */
169        public AbstractReasonerComponent getReasonerComponent() {
170                return rs;
171        }
172        
173        /**
174         * @return the la
175         */
176        public AbstractCELA getLearningAlgorithm() {
177                return la;
178        }
179    
180        /**
181         * @param args
182         * @throws ParseException
183         * @throws IOException
184         * @throws ReasoningMethodUnsupportedException
185         */
186        public static void main(String[] args) throws ParseException, IOException, ReasoningMethodUnsupportedException {
187                
188//              System.out.println("DL-Learner " + Info.build + " [TODO: read pom.version and put it here (make sure that the code for getting the version also works in the release build!)] command line interface");
189                System.out.println("DL-Learner command line interface");
190                
191                // currently, CLI has exactly one parameter - the conf file
192                if(args.length == 0) {
193                        System.out.println("You need to give a conf file as argument.");
194                        System.exit(0);
195                }
196                
197                // read file and print and print a message if it does not exist
198                File file = new File(args[args.length - 1]);
199                if(!file.exists()) {
200                        System.out.println("File \"" + file + "\" does not exist.");
201                        System.exit(0);
202                }
203                
204                Resource confFile = new FileSystemResource(file);
205                
206                List<Resource> springConfigResources = new ArrayList<>();
207
208        try {
209            //DL-Learner Configuration Object
210            IConfiguration configuration = new ConfParserConfiguration(confFile);
211
212            ApplicationContextBuilder builder = new DefaultApplicationContextBuilder();
213            ApplicationContext context =  builder.buildApplicationContext(configuration,springConfigResources);
214
215            // TODO: later we could check which command line interface is specified in the conf file
216            // for now we just use the default one
217
218            CLIBase2 cli;
219            if(context.containsBean("cli")) {
220                cli = (CLIBase2) context.getBean("cli");
221            } else {
222                cli = new CLI();
223            }
224            cli.setContext(context);
225            cli.setConfFile(file);
226            cli.run();
227        } catch (Exception e) {
228            String stacktraceFileName = "log/error.log";
229            
230            //Find the primary cause of the exception.
231            Throwable primaryCause = findPrimaryCause(e);
232
233            // Get the Root Error Message
234            logger.error("An Error Has Occurred During Processing.");
235            if (primaryCause != null) {
236                logger.error(primaryCause.getMessage());
237            }
238            logger.debug("Stack Trace: ", e);
239            logger.error("Terminating DL-Learner...and writing stacktrace to: " + stacktraceFileName);
240            createIfNotExists(new File(stacktraceFileName));
241
242            FileOutputStream fos = new FileOutputStream(stacktraceFileName);
243            PrintStream ps = new PrintStream(fos);
244            e.printStackTrace(ps);
245        }
246    }
247
248        public boolean isPerformCrossValidation() {
249                return performCrossValidation;
250        }
251
252        public void setPerformCrossValidation(boolean performCrossValiation) {
253                this.performCrossValidation = performCrossValiation;
254        }
255
256        public int getNrOfFolds() {
257                return nrOfFolds;
258        }
259
260        public void setNrOfFolds(int nrOfFolds) {
261                this.nrOfFolds = nrOfFolds;
262        }
263
264        //      public LearningAlgorithm getLearningAlgorithm() {
265//              return algorithm;
266//      }
267        
268        public KnowledgeSource getKnowledgeSource() {
269                return knowledgeSource;
270        }
271        
272}