/*
 * $Id: PatentsImporter.java,v 1.6 2005/03/21 20:30:06 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 * 
 * Created on 19.11.2004
 *
 * $Log: PatentsImporter.java,v $
 * Revision 1.6  2005/03/21 20:30:06  marbobo
 * + DocSize auf Type Long umgestellt
 *
 * Revision 1.5  2004/11/29 16:33:36  koppy
 * Verzeichnis für jedes importierte Patent
 *
 * Revision 1.4  2004/11/26 02:22:40  koppy
 * mini-bugfix
 *
 * Revision 1.3  2004/11/23 15:00:40  koppy
 * + zusätzlicher Parameter: -max_patents_per_dir
 * + korrekte Behandlung von Kategorienamen wie "EDV/Software-Entwicklung"
 *
 * Revision 1.2  2004/11/22 16:16:39  koppy
 * Importfunktion von Patenten verbessert: Es wird überprüft
 * ob schon ein gegebenes Patentdokument existiert...
 *
 * Revision 1.1  2004/11/22 12:52:09  koppy
 * + Import von Patenten zu Demo-/ Testzwecken
 *
 */
package vkc.ws.axis.service.patent;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Iterator;
import java.util.Properties;

import vkc.db.entities.VKCAclType;
import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCDynaAttribute;
import vkc.db.entities.VKCSubCategory;
import vkc.db.entities.VKCUser;
import vkc.db.serializer.VKCAclSerializer;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.db.serializer.VKCDocumentTypeSerializer;
import vkc.db.serializer.VKCUserSerializer;
import vkc.exception.AclException;
import vkc.exception.ConverterException;
import vkc.exception.DBException;
import vkc.security.PermissionManager;
import vkc.security.VKCAcl;
import vkc.server.archive.DataStoreException;
import vkc.util.Options;
import vkc.util.StringUtils;
import vkc.view.WebShare;
import vkc.ws.axis.service.SharkService;

/**
 * This class represents
 * @author Andreas Koop
 */
public class PatentsImporter {

    private File testPatentsDir = null;
    private VKCCategory patentsCategory = null;
    private VKCCategory issuedCategory = null;
    private int maxPatentsPerFile = Integer.MAX_VALUE;
    private VKCUser admin = null;
    

    public PatentsImporter(File testPatentsDir, VKCCategory patentsCat){
        
        if(testPatentsDir == null)
            throw new IllegalArgumentException("testPatentsDir must not be null!");
        
        if(!testPatentsDir.exists())
            throw new IllegalArgumentException(testPatentsDir.getAbsolutePath() + " does not exist!");

        if(!testPatentsDir.isDirectory())
            throw new IllegalArgumentException(testPatentsDir.getAbsolutePath() + " is not a directory!");
        
        if(patentsCat == null)
            throw new IllegalArgumentException("patentsCategory must not be null!");
        
        try {
            if(!PatentUtils.isCapablePatentCat(patentsCat))
                throw new IllegalArgumentException( patentsCat.getName() + " is not patentAppCapable!\n" +
                		"it must have the following dynamic Attribute/Value Pair defined: " 
                        + SharkService.ATTR_PATENT_APP_CAPABLE + "=true");
            
            this.testPatentsDir = testPatentsDir;
            this.patentsCategory = patentsCat;
            this.issuedCategory = PatentUtils.getIssuedCategory(this.patentsCategory);
            this.admin = VKCUserSerializer.retrieveUser( "Admin" );
            
        } catch (DBException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Exception while checking patent-capability");    
        } catch (AclException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Exception while checking patent-capability");    
        } 
        
    }
    
    
    /**
     * 
     */
    public void performImport() throws Exception {
        
        System.out.println( "Performing import from " +testPatentsDir.getAbsolutePath());
        System.out.println( "to " +patentsCategory.getAbsPathDescrString());
     
        File [] patentDirFiles = this.testPatentsDir.listFiles();
        for (int i = 0; i < patentDirFiles.length; i++) {
            File patentCatDir = patentDirFiles[i];
            if(!patentCatDir.isDirectory()){
                continue;
            }
            
            importPatents(patentCatDir);
            
        }
    }
    
    
    
    /**
     * @param patentCatDir
     */
    public void importPatents(File patentCatDir) throws Exception{
        System.out.println( "[INFO] Importing Patents from " + patentCatDir.getAbsolutePath());
        
        File metaData = new File(patentCatDir, "MetaData.properties");
        
        if(!metaData.exists()){
            System.out.println( "[SEVERE] " + metaData.getAbsolutePath() + " does not exist!");
            return;
        }
        
        Properties metaProps = new Properties();
        metaProps.load( new FileInputStream(metaData) );
        
        if( metaProps.getProperty( "VKCState" ) == null
             || !metaProps.getProperty( "VKCState" ).equalsIgnoreCase( "ISSUED")){
            System.out.println( "[SEVERE] " + metaData.getName()+ " does not contain \"VKCState=ISSUED\"!");
            return;
        }
        
        if( metaProps.getProperty( "VKCCategory" ) == null ){
            System.out.println( "[SEVERE] " + metaData.getName()+ " does not contain \"VKCCategory\"-property!");
            return;
        }
        
        VKCCategory patentCategoryCat = this.getPatentCategory( metaProps );
        
		// Patente importieren
		File [] patentFiles = patentCatDir.listFiles();
		int importedPatentsCount = 0;
		for (int i = 0; i < patentFiles.length; i++) {
            File patentFile = patentFiles[i];
            
            if(patentFile.getName().endsWith( ".properties")){
                continue;
            }
            
            if(importedPatentsCount >= maxPatentsPerFile){
                break;
            }
            
            try {
                
                if( this.existsPatentDocument(patentCategoryCat, patentFile.getName())){
                    System.out.println("[FINE] Patent " + patentFile.getAbsolutePath() + " already imported!" );
                    importedPatentsCount++;
                    continue;
                }
                VKCDocument patentDoc = importPatent(patentCategoryCat, patentFile);
                
                // Stand d. Technik Dok.. extrahieren
                String sdtSection = PatentUtils.extractStdT(patentDoc, 
                        metaProps.getProperty("STDT_START"),
                        metaProps.getProperty("STDT_END"));
                
                if(StringUtils.isEmpty(sdtSection)){
    			    sdtSection = "Nichts gefunden für";
    			    sdtSection+= "\nSTDT_START="+metaProps.getProperty("STDT_START");
    			    sdtSection+= "\nSTDT_END="+metaProps.getProperty("STDT_END");
    			}
    			
                VKCDocument patentStdTDoc = new VKCDocument();

        		patentStdTDoc.setCategoryId( patentDoc.getCategoryId() );
        		patentStdTDoc.setPublished( new Date() );
        		patentStdTDoc.setLastAccessed( null );
        		patentStdTDoc.setLastAccessorId( null );
        		patentStdTDoc.setLastChanged( new Date() );
        		patentStdTDoc.setLastChangerId( admin.getUserId() );
        		
                patentStdTDoc.setPublisherId( admin.getUserId());
        		patentStdTDoc.setTitle( patentDoc.getTitle() + ":Stand der Technik" );
        		
    			patentStdTDoc.setName( patentDoc.getTitle()+ "_StdT.txt" );
    			patentStdTDoc.setArchiveId( WebShare.archive.store( sdtSection.getBytes() ) );
    			patentStdTDoc.setDocSize( new Long(sdtSection.getBytes().length ));
                patentStdTDoc.setZipped( new Integer( 0 ) );
    			patentStdTDoc.setDocumentType( VKCDocumentTypeSerializer.getDocumentTypeByExtension( "TXT" ) );
    			
    			VKCDynaAttribute a = new VKCDynaAttribute();
    			a.setDynaAttrId( new Integer( -1 ) );
    			a.setName( SharkService.ATTR_STATE_OF_THE_ART_DOC );
    			a.setValue( "true" );
    			
    			patentStdTDoc.addDynaAttribute(a);
    			
    			PatentUtils.convertAndSave(patentStdTDoc);
    			importedPatentsCount++;
    			
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (DataStoreException e) {
                e.printStackTrace();
            } catch (DBException e) {
                e.printStackTrace();
            } catch (ConverterException e) {
                e.printStackTrace();
            }
            
        }
    }


    /**
     * @param patentCategoryCat
     * @param name
     * @return
     */
    private boolean existsPatentDocument(VKCCategory patentCategoryCat, String name) {
        
        if(StringUtils.isEmpty(name)){
            return false;
        }
        
        for(Iterator it = patentCategoryCat.getSubCategories().iterator(); it.hasNext();){
            VKCSubCategory subCat = (VKCSubCategory)it.next();
            if(name.substring(0, name.lastIndexOf('.')).equals(subCat.getName())){
                return true;
            }
        }
        
        return false;
    }


    /**
     * @param patentCategoryCat
     * @param patentFile
     * @throws DataStoreException
     * @throws FileNotFoundException
     * @throws DBException
     * @throws ConverterException
     */
    public VKCDocument importPatent(VKCCategory patentCategoryCat, File patentFile) 
    	throws DataStoreException, FileNotFoundException, DBException, ConverterException, AclException{
        
        System.out.println("[INFO] Importing Patent " + patentFile.getAbsolutePath());
        
        VKCCategory newCat = new VKCCategory();
        newCat.setName( patentFile.getName().substring(0, patentFile.getName().lastIndexOf('.')));
        newCat.setParentCategoryId(patentCategoryCat.getCategoryId());
        newCat.setAcl( this.getAclFromIssuedCategory() );
        		
		VKCCategorySerializer.saveCategory( newCat );
		patentCategoryCat.addSubCategory(new VKCSubCategory( newCat.getCategoryId(), newCat.getName()));
		
		System.out.println( "[INFO] " + newCat.getAbsPathDescrString() + " angelegt!");
		
        
        VKCDocument patentDoc = new VKCDocument();

        patentDoc.setCategoryId( newCat.getCategoryId() );
        patentDoc.setPublished( new Date() );
        patentDoc.setLastAccessed( null );
        patentDoc.setLastAccessorId( null );
        patentDoc.setLastChanged( new Date() );
        patentDoc.setLastChangerId( admin.getUserId() );
        
        patentDoc.setPublisherId( admin.getUserId());
        patentDoc.setTitle( patentFile.getName().substring(0, patentFile.getName().lastIndexOf( "." )) );
        patentDoc.setName( patentFile.getName() );
        patentDoc.setArchiveId( WebShare.archive.store( new FileInputStream(patentFile) ) );    
        
        patentDoc.setDocSize( new Long( patentFile.length() ));
        patentDoc.setZipped( new Integer( 0 ) );
        patentDoc.setDocumentType( VKCDocumentTypeSerializer.getDocumentTypeByExtension( 
                patentFile.getName().substring(patentFile.getName().lastIndexOf( "." )+1)));

        // Dynamische Attribute
        VKCDynaAttribute status = new VKCDynaAttribute();
        status.setDynaAttrId( new Integer( -1 ) );
        status.setName( SharkService.ATTR_STATUS );
        status.setValue( SharkService.CONFIRMED );
        patentDoc.addDynaAttribute(status);
        
        VKCDynaAttribute relLit = new VKCDynaAttribute();
        relLit.setDynaAttrId( new Integer( -1 ) );
        relLit.setName( SharkService.ATTR_PATENT_RELEVANT_LITERATURE );
        relLit.setValue( "false" );
        patentDoc.addDynaAttribute(relLit);
        
        VKCDynaAttribute formalCorrect = new VKCDynaAttribute();
        formalCorrect.setDynaAttrId( new Integer( -1 ) );
        formalCorrect.setName( SharkService.ATTR_FORMAL_CORRECT );
        formalCorrect.setValue( "true" );
        patentDoc.addDynaAttribute(formalCorrect);
        
        VKCDynaAttribute chosenCategory = new VKCDynaAttribute();
        chosenCategory.setDynaAttrId( new Integer( -1 ) );
        chosenCategory.setName( SharkService.ATTR_CHOSEN_CATEGORY );
        chosenCategory.setValue( this.issuedCategory.getCategoryId().toString() );
        patentDoc.addDynaAttribute(chosenCategory);
        
        PatentUtils.convertAndSave(patentDoc);
        
        return patentDoc;
    }

    
    /**
     * @param catName
     * @return
     */
    private VKCCategory getPatentCategory(Properties metaProps) throws DBException, AclException {
        
        String [] cats = metaProps.getProperty( "VKCCategory" ).split( "/" );
        
        VKCCategory currentCat = this.issuedCategory;
        
        for (int i = 0; i < cats.length; i++) {
            String currentCatname = cats[i];
            boolean found = false;
            
            for(Iterator it = currentCat.getSubCategories().iterator(); it.hasNext();){
                VKCSubCategory subCat = (VKCSubCategory)it.next();
                if(subCat.getName().equals(currentCatname)){
                    
                    currentCat = VKCCategorySerializer.retrieveCategory(subCat.getSubCategoryId());
                    if(i == cats.length-1){
                        return currentCat;
                    }
                    
                    found = true;
                    break;
                }
            }
            
            if(!found){
                
                VKCCategory newCat = new VKCCategory();
                newCat.setName( currentCatname );
                newCat.setParentCategoryId(currentCat.getCategoryId());
                newCat.setAcl( this.getAclFromIssuedCategory() );
                
                if(i == cats.length-1){
                    newCat.setKeywordsByString( metaProps.getProperty( "Keywords", "") );    
                }
    			
    			VKCCategorySerializer.saveCategory( newCat );
    			currentCat.addSubCategory(new VKCSubCategory( newCat.getCategoryId(), newCat.getName()));
    			currentCat = newCat;
    			System.out.println( "[INFO] " + newCat.getAbsPathDescrString() + " angelegt!");
            }
        }
        
        
        return currentCat;
    }

    /**
     * HElper method
     * @return
     */
    private VKCAcl getAclFromIssuedCategory() throws DBException, AclException{
        
        VKCAcl acl = VKCAclSerializer.getAclByCategoryId( this.issuedCategory.getCategoryId() );
        PermissionManager.setCategoryOwnerPermissions( new Integer( VKCAclType.USER_TYPE ),
                this.issuedCategory.getCreatorId(), this.issuedCategory.getCreatorId(), acl );
    
		acl.setAclId(null);
		
		return acl;
    }
    
    public void setMaxPatentsPerFile(int maxPatentsPerFile) {
        this.maxPatentsPerFile = maxPatentsPerFile;
    }


    private static void usage(){
        System.out.println("Usage: java " + PatentsImporter.class.getName() 
                + " -patents_dir <dir> -patents_cat_id <categoryID>");
        System.exit(-1);
    }
    
    public static void main ( String [] args) throws Exception{
        Options ops = new Options(args);
        
        if(!ops.has("patents_dir")){
            usage();
        }
        
        if(!ops.has("patents_cat_id")){
            usage();
        }
        
        // Init VKC Application
    	File webApplicationDir = new File( new File("."), "defaultroot" );
    	
    	if( !webApplicationDir.exists())
    		throw new Exception( "Web Apps dir does not exist: " + webApplicationDir.getAbsolutePath() );

    	WebShare.init( webApplicationDir.getAbsolutePath() );
        
        File patentsDir = new File(ops.getOption("patents_dir"));
        VKCCategory patentsCat = VKCCategorySerializer.retrieveCategory(
                				new Integer(ops.getOption("patents_cat_id")));
        PatentsImporter importer = new PatentsImporter( patentsDir, patentsCat);
        
        if(ops.has("max_patents_per_dir")){
            importer.setMaxPatentsPerFile(Integer.parseInt(ops.getOption("max_patents_per_dir")));
        }
        importer.performImport();
        
        WebShare.shutdown();
    }
    
    
}
