bool processmodel(const string & inputmodelfile, int inputmodeltype, const string & outputmodelfile, int outputmodeltype, const string & corpusfile,   PatternSetModel * constrainbymodel, IndexedCorpus * corpus, PatternModelOptions & options, bool continued, bool expand, int firstsentence, bool ignoreerrors, string inputmodelfile2, ClassDecoder * classdecoder,  ClassEncoder * classencoder, bool print, bool report, bool nocoverage, bool histogram , bool query, string dorelations, bool doinstantiate, bool info, bool printreverseindex, int cooc, double coocthreshold, bool flexfromskip, const vector<string> & querypatterns) {
    if (!(print || report || histogram || query || info || cooc || printreverseindex || (dorelations != "") || (!querypatterns.empty()) || (!outputmodelfile.empty()) )) {
        cerr << "Ooops... You didn't really give me anything to do...that can't be right.. Please study the usage options (-h) again! Did you perhaps forget a --print or --outputmodel? " << endl;
        return false;
    }

    ModelType * inputmodel;

    string outputqualifier = "";
    if ((outputmodeltype == UNINDEXEDPATTERNMODEL) || (outputmodeltype == UNINDEXEDPATTERNPOINTERMODEL)) {
        outputqualifier += " unindexed";
    }
    if ((outputmodeltype == INDEXEDPATTERNPOINTERMODEL) || (outputmodeltype == UNINDEXEDPATTERNPOINTERMODEL)) {
        outputqualifier += " pointer";
    }

    if (inputmodelfile.empty()) {
        //train model from scratch

        inputmodel = new ModelType(corpus);


        cerr << "Training" << outputqualifier << " model on  " << corpusfile <<endl;
        inputmodel->train(corpusfile, options, constrainbymodel, NULL, continued,firstsentence,ignoreerrors);
        if (constrainbymodel) {
            cerr << "Unloading constraint model" << endl;
            delete constrainbymodel;
            constrainbymodel = NULL;
        }

        if (options.DOSKIPGRAMS) {
            if ((inputmodeltype == UNINDEXEDPATTERNMODEL) || (inputmodeltype == UNINDEXEDPATTERNPOINTERMODEL)) {
                cerr << "WARNING: Can't compute skipgrams non-exhaustively on unindexed model" << endl;
                if (flexfromskip) cerr << "WARNING: Can't compute flexgrams from skipgrams on unindexed model" << endl;
            }  else {
                if (!inputmodelfile2.empty()) cerr << "WARNING: Can not compute skipgrams constrained by " << inputmodelfile2 << "!" << endl;
                if (!inputmodel->hasskipgrams) {
                    cerr << "Computing skipgrams" << endl;
                    inputmodel->trainskipgrams(options);
                }
                if (flexfromskip) {
                    cerr << "Computing flexgrams from skipgrams" << corpusfile <<endl;
                    int found = inputmodel->computeflexgrams_fromskipgrams();
                    cerr << found << " flexgrams found" << corpusfile <<endl;
                }
            }
        }

    } else {
        //load model

        cerr << "Loading pattern model " << inputmodelfile << " as" << outputqualifier << " model..."<<endl;
        inputmodel = new ModelType(inputmodelfile, options, (PatternModelInterface*) constrainbymodel, corpus);
        if ((corpus != NULL) && (inputmodel->hasskipgrams)) {
            cerr << "Filtering skipgrams..." << endl;
            inputmodel->pruneskipgrams(options.MINTOKENS, options.MINSKIPTYPES);
        }

        if ((!corpusfile.empty()) && (expand)) {
            cerr << "Expanding model on  " << corpusfile <<endl;
            inputmodel->train(corpusfile, options, constrainbymodel,NULL,  continued,firstsentence,ignoreerrors);
            if (constrainbymodel) {
                cerr << "Unloading constraint model" << endl;
                delete constrainbymodel;
                constrainbymodel = NULL;
            }
        } else if (options.DOSKIPGRAMS) {
            if (constrainbymodel) {
                cerr << "Unloading constraint model" << endl;
                delete constrainbymodel;
                constrainbymodel = NULL;
            }
            cerr << "Computing skipgrams" << endl;
            if (!inputmodelfile2.empty()) cerr << "WARNING: Can not compute skipgrams constrained by " << inputmodelfile2 << "!" << endl;
            inputmodel->trainskipgrams(options);
            if (flexfromskip) {
                cerr << "Computing flexgrams from skipgrams" << corpusfile <<endl;
                int found = inputmodel->computeflexgrams_fromskipgrams();
                cerr << found << " flexgrams found" << corpusfile <<endl;
            }
        } else {
            if (constrainbymodel) {
                cerr << "Unloading constraint model" << endl;
                delete constrainbymodel;
                constrainbymodel = NULL;
            }
        }
    }


    if (!outputmodelfile.empty()) {
        cerr << "Writing model to " << outputmodelfile << endl;
        inputmodel->write(outputmodelfile);
    }
    viewmodel<ModelType>(*inputmodel, classdecoder, classencoder, print, report, nocoverage, histogram, query, dorelations, doinstantiate, info, printreverseindex, cooc, coocthreshold);

    if (!querypatterns.empty()) {
        processquerypatterns<ModelType>(*inputmodel,  classencoder, classdecoder, querypatterns, dorelations, doinstantiate);
    }

    delete inputmodel;

    return true;
}