/*
 * $Id: PatentUtils.java,v 1.11 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 07.10.2004
 *
 * $Log: PatentUtils.java,v $
 * Revision 1.11  2005/03/21 20:30:06  marbobo
 * + DocSize auf Type Long umgestellt
 *
 * Revision 1.10  2004/12/23 16:18:18  koppy
 * PARelevantLiteratur=false für alle Ergebnisdokumente
 *
 * Revision 1.9  2004/12/21 10:29:17  koppy
 * so einiges
 *
 * Revision 1.8  2004/11/26 02:22:40  koppy
 * mini-bugfix
 *
 * Revision 1.7  2004/11/23 15:02:02  koppy
 * Refactoring: convert(..) --> convertAndSave(..)
 *
 * Revision 1.6  2004/11/22 16:16:39  koppy
 * Importfunktion von Patenten verbessert: Es wird überprüft
 * ob schon ein gegebenes Patentdokument existiert...
 *
 * Revision 1.5  2004/11/22 12:52:09  koppy
 * + Import von Patenten zu Demo-/ Testzwecken
 *
 * Revision 1.4  2004/11/09 14:35:40  marbobo
 * + Umstellung von authorId auf publisherId
 * + Hinzufügen von AuthorName für Dokumente
 * + Nötwendige Änderungen betreffend AuthorName und PublisherId
 *
 * Revision 1.3  2004/10/13 13:53:55  koppy
 * +doLiteraturResearch
 * +getNextNewSimilarStdTDoc
 * +isStdTResearchDone
 * +computeSimilaStdTDocs
 * +setPatentAcceptes
 * implementiert. Muss aber noch intensiv getestet/verbessert werden.
 *
 * Revision 1.2  2004/10/11 13:16:52  koppy
 * Vetogeschichten implementiert
 *
 * Revision 1.1  2004/10/09 16:03:01  koppy
 * Initiale Version
 *
 * Revision 1.1  2004/10/08 14:00:26  koppy
 * initial check in
 *
 */
package vkc.ws.axis.service.patent;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.axis.MessageContext;

import vkc.converter.DocConverter;
import vkc.converter.TdfDocConverter;
import vkc.converter.common.ConversionResponse;
import vkc.db.entities.VKCAclType;
import vkc.db.entities.VKCAdditionalDocumentFormat;
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.VKCDocumentFormatSerializer;
import vkc.db.serializer.VKCDocumentSerializer;
import vkc.db.serializer.VKCDocumentTypeSerializer;
import vkc.exception.AclException;
import vkc.exception.ConverterException;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.search.ClassifyResultEntry;
import vkc.security.PermissionManager;
import vkc.security.VKCAcl;
import vkc.server.ConverterProxy;
import vkc.server.archive.DataStoreException;
import vkc.util.CategoryUtils;
import vkc.util.StringUtils;
import vkc.view.WebShare;
import vkc.ws.axis.service.SharkService;

/**
 * This class represents
 * @author Andreas Koop
 */
public final class PatentUtils {
    
    
    
    /**
     * Es wird das älteste Dokument (Zeitstempel!) ohne dynamische Attribute 
     * der gegebenen Kategorie (mit dyn. Attribut <code>SharkService.INCOMING_CAT</code>=true) ermittelt.
     * @param incomingCat
     * @return das gesuchte Dokument. null, falls nicht vorhanden.
     */
    public static final VKCDocument getOldestDocumentWithoutDynaAttributes( VKCCategory incomingCat ){
        
	    Collection docs = incomingCat.getDocuments();
	    VKCDocument oldestPatentAppDoc = null;
	    
	    for (Iterator iterator = docs.iterator(); iterator.hasNext();) {
            VKCDocument doc = (VKCDocument) iterator.next();

			if( doc.getDynaAttributes().size() > 0)
			    continue;
			
			if(oldestPatentAppDoc == null || doc.getPublished().before(oldestPatentAppDoc.getPublished())){
			    oldestPatentAppDoc = doc;
			}
        }
	    
	    return oldestPatentAppDoc;
    }
    

    /**
     * Gibt die Kategorie "Patente/Neuzugänge" zurück;
     * eine Kategorie mit dynamischem Attribut <code>SharkService.INCOMING_CAT</code>
     * mit Wert <code>true</code>.
     * @param patentsCat Die Patentkategorie
     * @return null, falls nicht vorhanden.
     */
    public static final VKCCategory getIncomingCategory(VKCCategory patentsCat) 
    	throws DBException {
        
        return PatentUtils.getCategoryWithDynaAttribute(
                patentsCat, SharkService.ATTR_INCOMING_CAT, "true");
        
    }
    
    /**
     * Gibt die Kategorie "Patente/Erteilte Patente" zurück;
     * eine Kategorie mit dynamischem Attribut <code>SharkService.ATTR_ISSUED_CAT</code>
     * mit Wert <code>true</code>.
     * @param patentsCat Die Patentkategorie
     * @return null, falls nicht vorhanden.
     */
    public static final VKCCategory getIssuedCategory(VKCCategory patentsCat) 
    	throws DBException {
        
        return PatentUtils.getCategoryWithDynaAttribute(
                patentsCat, SharkService.ATTR_ISSUED_CAT, "true");
        
    }
    
    /**
     * Gibt die Kategorie "Patente/Abgewiesene Patente" zurück;
     * eine Kategorie mit dynamischem Attribut <code>SharkService.ATTR_REJECTED_CAT</code>
     * mit Wert <code>true</code>.
     * @param patentsCat Die Patentkategorie
     * @return null, falls nicht vorhanden.
     */
    public static final VKCCategory getRejectedCategory(VKCCategory patentsCat) 
    	throws DBException {
        
        return PatentUtils.getCategoryWithDynaAttribute(
                patentsCat, SharkService.ATTR_REJECTED_CAT, "true");
        
    }

    /**
     * Überprüft, ob die übergebene Kategorie das dynamische Attribute
     * <code>SharkService.ATTR_PATENT_APP_CAPABLE</code> hat und
     * dieses auf true gesetzt ist. und alle benötigten Unterkategorien 
     * vorhanden sind (also Unterkategorien mit den erforderlichen dyn. 
     * Attributen wie z.B. "IncomingCat"). Falls die erforderlichen
     * Kategorien nicht vorhanden sind, werden sie angelegt.
     * 
     * @param potentialPatentCat die zu überprüfende KAtegorie
     * @return true, falls gültige Patentkategorie, false sonst.
     */
    public static boolean isCapablePatentCat(VKCCategory potentialPatentCat) 
    	throws DBException, AclException{
        
        if(potentialPatentCat == null){
            VKCLogManager.infoLog( PatentUtils.class, "potentialPatentCat ist null!" );
            return false;
        }
        
        VKCDynaAttribute patentCapAttr = potentialPatentCat.getDynaAttribute( SharkService.ATTR_PATENT_APP_CAPABLE);
        
        if(patentCapAttr == null)
            return false;
        
        if(!patentCapAttr.getValue().equalsIgnoreCase( "true" ))
            return false;
        
        
        // Gibts es das PAStdTStart-Attribut?
        // Falls nicht, wird es angelegt
        VKCDynaAttribute stdtStart = potentialPatentCat.getDynaAttribute( SharkService.ATTR_STDT_START );
        
        if(stdtStart == null){
            VKCDynaAttribute stdtStartAttr = new VKCDynaAttribute();
			stdtStartAttr.setDynaAttrId( new Integer( -1 ) );
			stdtStartAttr.setName( SharkService.ATTR_STDT_START );
			stdtStartAttr.setValue( SharkService.DEFAULT_STDT_START );
			potentialPatentCat.addDynaAttribute(stdtStartAttr);
			
        }
        
        // Gibts es das PAStdTStart-Attribut?
        // Falls nicht, wird es angelegt
        VKCDynaAttribute stdtEnd = potentialPatentCat.getDynaAttribute( SharkService.ATTR_STDT_END );
        
        if(stdtEnd == null){
            VKCDynaAttribute stdtEndAttr = new VKCDynaAttribute();
			stdtEndAttr.setDynaAttrId( new Integer( -1 ) );
			stdtEndAttr.setName( SharkService.ATTR_STDT_END );
			stdtEndAttr.setValue( SharkService.DEFAULT_STDT_END);
			potentialPatentCat.addDynaAttribute(stdtEndAttr);
        }
        
        
        if(stdtStart == null || stdtEnd == null){
            VKCCategorySerializer.saveCategory(potentialPatentCat);
        }
        
        
        if( !PatentUtils.hasIncomingCategory(potentialPatentCat)){
            // Es existiert keine Incoming-Kategorie für Neuzugänge...
            // -> Anlegen!
            VKCAcl acl = VKCAclSerializer.getAclByCategoryId( potentialPatentCat.getCategoryId() );
            PermissionManager.setCategoryOwnerPermissions( new Integer( VKCAclType.USER_TYPE ),
                    potentialPatentCat.getCreatorId(), potentialPatentCat.getCreatorId(), acl );
        
    		acl.setAclId(null);
    		
    		VKCDynaAttribute a = new VKCDynaAttribute();
			a.setDynaAttrId( new Integer( -1 ) );
			a.setName( SharkService.ATTR_INCOMING_CAT );
			a.setValue( "true" );
			
    		VKCCategory incomingCategory = new VKCCategory();
    		incomingCategory.setName( "Neuzugänge" );
            incomingCategory.setParentCategoryId(potentialPatentCat.getCategoryId());
    		incomingCategory.setAcl(acl);
			incomingCategory.addDynaAttribute( a );
			
    		VKCCategorySerializer.saveCategory( incomingCategory );
    		potentialPatentCat.addSubCategory( new VKCSubCategory(incomingCategory.getCategoryId(), incomingCategory.getName()));
            
        }
        
        if( !PatentUtils.hasIssuedCategory(potentialPatentCat)){
            // Es existiert keine "Issued"-Kategorie für "Erteilte Patente"...
            // -> Anlegen!
            VKCAcl acl = VKCAclSerializer.getAclByCategoryId( potentialPatentCat.getCategoryId() );
            PermissionManager.setCategoryOwnerPermissions( new Integer( VKCAclType.USER_TYPE ),
                    potentialPatentCat.getCreatorId(), potentialPatentCat.getCreatorId(), acl );
    		acl.setAclId(null);
    		
    		VKCDynaAttribute a = new VKCDynaAttribute();
			a.setDynaAttrId( new Integer( -1 ) );
			a.setName( SharkService.ATTR_ISSUED_CAT);
			a.setValue( "true" );
			
			VKCDynaAttribute b = new VKCDynaAttribute();
			b.setDynaAttrId( new Integer( -1 ) );
			b.setName( SharkService.ATTR_PATENT_RELEVANT_LITERATURE);
			b.setValue( "true" );
			
    		VKCCategory issuedCategory = new VKCCategory();
    		issuedCategory.setName( "Erteilte Patente" );
            issuedCategory.setParentCategoryId(potentialPatentCat.getCategoryId());
    		issuedCategory.setAcl(acl);
			issuedCategory.addDynaAttribute( a );
			issuedCategory.addDynaAttribute( b );
			
    		VKCCategorySerializer.saveCategory( issuedCategory );
    		potentialPatentCat.addSubCategory( new VKCSubCategory(issuedCategory.getCategoryId(), issuedCategory.getName()));    		
        }
        
        if( !PatentUtils.hasRejectedCategory(potentialPatentCat)){
            // Es existiert keine "Abgewiesene Patente"-Kategorie ...
            // -> Anlegen!
            VKCAcl acl = VKCAclSerializer.getAclByCategoryId( potentialPatentCat.getCategoryId() );
            PermissionManager.setCategoryOwnerPermissions( new Integer( VKCAclType.USER_TYPE ),
                    potentialPatentCat.getCreatorId(), potentialPatentCat.getCreatorId(), acl );
    		acl.setAclId(null);
    		
    		VKCDynaAttribute a = new VKCDynaAttribute();
			a.setDynaAttrId( new Integer( -1 ) );
			a.setName( SharkService.ATTR_REJECTED_CAT);
			a.setValue( "true" );
			
    		VKCCategory rejectedCategory = new VKCCategory();
    		rejectedCategory.setName( "Abgewiesene Patente" );
            rejectedCategory.setParentCategoryId(potentialPatentCat.getCategoryId());
    		rejectedCategory.setAcl(acl);
			rejectedCategory.addDynaAttribute( a );
			
    		VKCCategorySerializer.saveCategory( rejectedCategory );
    		potentialPatentCat.addSubCategory( new VKCSubCategory(rejectedCategory.getCategoryId(), rejectedCategory.getName()));
    		
        }
           
        return true;
    }
    
        
    /**
     * Überprüft, ob die gegebene Kategorie
     * eine "Incoming"-Kateogorie enthält, also z.B PAtente/Neuzugänge
     * @param potentialPatentCat
     * @return
     * @throws DBException
     */
	 public static final boolean hasIncomingCategory( VKCCategory potentialPatentCat ) 
	 	throws DBException {
	     
	     return PatentUtils.hasCategoryWithDynaAttribute(potentialPatentCat, 
		            SharkService.ATTR_INCOMING_CAT, "true");
	 }
	 
	 /**
     * Überprüft, ob die gegebene Kategorie
     * eine "Issued"-Kateogorie enthält, also PAtente/Erteilte Patente
     * @param potentialPatentCat
     * @return
     * @throws DBException
     */
	 public static final boolean hasIssuedCategory( VKCCategory potentialPatentCat ) 
	 	throws DBException {
	    return PatentUtils.hasCategoryWithDynaAttribute(potentialPatentCat, 
	            SharkService.ATTR_ISSUED_CAT, "true");
	 }
	 
	 /**
     * Überprüft, ob die gegebene Kategorie
     * eine "Abgewiesene Patente"-Kateogorie enthält
     * @param potentialPatentCat
     * @return
     * @throws DBException
     */
	 public static final boolean hasRejectedCategory( VKCCategory potentialPatentCat ) 
	 	throws DBException {
	    return PatentUtils.hasCategoryWithDynaAttribute(potentialPatentCat, 
	            SharkService.ATTR_REJECTED_CAT, "true");
	 }
	 
	 /**
	  * Gibt es eine Unterkategorie der gegebenen KAtegorie,
	  * die das gegebene dynamische Attribut besitzt?
	  * 
	  * @param cat eine KAtegorie
	  * @param attrName NAme eines dynamischen Attributes
	  * @param value Wert des dynamischen Attributes
	  * @return 
	  * @throws DBException
	  */
	 public static final boolean hasCategoryWithDynaAttribute(VKCCategory cat,
            String attrName, String value) throws DBException {

        for (Iterator iter = cat.getSubCategoriesIds().iterator(); iter
                .hasNext();) {

            VKCCategory subCat = VKCCategorySerializer.retrieveCategory((Integer) iter.next());
            VKCDynaAttribute attrIncommingCat = subCat.getDynaAttribute(attrName);

            if (attrIncommingCat != null
                    && attrIncommingCat.getValue().equalsIgnoreCase(value)) {
                return true;
            }

        }

        return false;
	 }
	 
	 /**
	  * 
	  * @param attrs
	  * @param attrName
	  * @param value
	  * @return
	  * @throws DBException
	  */
	 public static final boolean hasDynaAttribute(Collection attrs,
            String attrName, String value) {

        for (Iterator iter = attrs.iterator(); iter.hasNext();) {

            VKCDynaAttribute attr = (VKCDynaAttribute) iter.next();

            if (attr.getName().equalsIgnoreCase(attrName)
                    && attr.getValue().equalsIgnoreCase(value)) {
                return true;
            }

        }

        return false;
    }
	 
	 /**
	  * Gibt es ein Dokument der gegebenen KAtegorie,
	  * die das gegebene dynamische Attribut besitzt?
	  * 
	  * @param cat eine KAtegorie
	  * @param attrName NAme eines dynamischen Attributes
	  * @param value Wert des dynamischen Attributes
	  * @return 
	  * @throws DBException
	  */
	 public static final boolean hasDocumentWithDynaAttribute(VKCCategory cat,
            String attrName, String value) {

        for (Iterator iter = cat.getDocuments().iterator(); iter.hasNext();) {

            VKCDocument doc = (VKCDocument)iter.next();
            VKCDynaAttribute attr = doc.getDynaAttribute(attrName);

            if (attr != null
                    && attr.getValue().equalsIgnoreCase(value)) {
                return true;
            }

        }

        return false;
    }
	 
	 /**
	  * Gibt eine Unterkategorie der gegebenen KAtegorie,
	  * die das gegebene dynamische Attribut besitzt zurück
	  * 
	  * @param cat eine KAtegorie
	  * @param attrName NAme eines dynamischen Attributes
	  * @param value Wert des dynamischen Attributes
	  * @return 
	  * @throws DBException
	  */
	 public static final VKCCategory getCategoryWithDynaAttribute(VKCCategory cat,
            String attrName, String value) throws DBException {

        for (Iterator iter = cat.getSubCategoriesIds().iterator(); iter
                .hasNext();) {

            VKCCategory subCat = VKCCategorySerializer.retrieveCategory((Integer) iter.next());
            VKCDynaAttribute attrIncommingCat = subCat.getDynaAttribute(attrName);

            if (attrIncommingCat != null
                    && attrIncommingCat.getValue().equalsIgnoreCase(value)) {
                return subCat;
            }

        }

        return null;
    }
    
    
	 /**
     * @param patentDoc
     * @param secion Name des zu extrahierenden Abschnittes "Description"
     * @param sectionEndPhrases String von Phrasen durch ";" separiert, 
     * die das Ende des zu extrahierenden Abschnittes markieren (exklusiv)
     * @return
     * @throws DataStoreException
     * @throws IOException
     */
    public static final String extractStdT(VKCDocument patentDoc, String section) 
    	throws DataStoreException, ConverterException, DBException{
    
        return PatentUtils.extractStdT(patentDoc, section, "");
    }
	    
	 /**
     * @param patentDoc
     * @param secion Name des zu extrahierenden Abschnittes "Description"
     * @param sectionEndPhrases String von Phrasen durch ";" separiert, 
     * die das Ende des zu extrahierenden Abschnittes markieren (exklusiv)
     * @return
     * @throws DataStoreException
     * @throws IOException
     */
    public static final String extractStdT(VKCDocument patentDoc, String section, String sectionEndPhrases) 
    	throws DataStoreException, ConverterException, DBException{
    
        return PatentUtils.extractStdT(patentDoc, section, 
                    PatentUtils.getSectionEndPhrases(sectionEndPhrases));
        
    }

    
    /**
     * @param patentDoc
     * @param secion Name des zu extrahierenden Abschnittes "Description"
     * @param sectionEndPhrases Menge von Phrasen, die das Ende des zu extrahierenden
     * Abschnittes markieren (exklusiv)
     * @return
     * @throws DataStoreException
     * @throws IOException
     */
    public static final String extractStdT(VKCDocument patentDoc, String section, Set sectionEndPhrases) 
    	throws DataStoreException, ConverterException, DBException{
        
        Collection addDocs = patentDoc.getAdditionalDocumentFormats(); 
		if(addDocs.size() == 0 ){
		    PatentUtils.convertAndSave(patentDoc);
		    addDocs = patentDoc.getAdditionalDocumentFormats();
		}
		
		for (Iterator iter = addDocs.iterator(); iter.hasNext();) {
            VKCAdditionalDocumentFormat f = (VKCAdditionalDocumentFormat) iter.next();
            if (!f.getDocTypeId().equals(new Integer(DocConverter.tdf)))
            	continue;
            
            // TDF Dokument vorhanden
            InputStream tdfStream = f.getInputStream();
            //System.out.println( FileUtils.toStringBuffer(tdfStream).toString() );
            
            DocConverter converter = DocConverter.createConverter( tdfStream, f.getDocTypeId().intValue());
            converter.convert( tdfStream, null );
            
            return ((TdfDocConverter)converter).getSection( section, sectionEndPhrases ).toString();
        }
		
		return null;
    }

    
    /**
     * 
     * @param doc
     * @return
     * @throws DBException
     * @throws ConverterException
     */
    public static final boolean convertAndSave( VKCDocument doc) throws DBException, ConverterException {
        
        ConverterProxy converter 	= new ConverterProxy();
		ConversionResponse response = converter.convert(doc);
		
		if( response == null)
		    return false;
		    
	    Collection addDocFormats = response.getAdditionalDocFormats();
	    
	    if(addDocFormats == null)
	        return false;
	    
	    doc.setAdditionalDocumentFormats( addDocFormats ); 
		
	    // Index aktualisieren
	    VKCDocumentSerializer.saveDocument(doc, true, false);
		VKCDocumentFormatSerializer.saveAdditionalDocumentFormats( doc.getDocumentId(), 
						addDocFormats);
		
		
		return true;
    }


    /**
     * Führt die Klassifizierung mit dem gegebenen Klassifizierer durch
     * @param classifier
     * @param patentApplDocId
     * @param categoryId
     * @return
     */
    public static final String classify(PatentClassifier classifier, VKCDocument patentDoc, String categoryId) 
    	throws Exception{
        
        if (StringUtils.isEmpty(categoryId)){
			return "";
		}
   
		// Hier Implementierung der eigentlichen Funktionalität. 
		VKCUser user = (VKCUser)MessageContext.getCurrentContext().getProperty( MessageContext.AUTHUSER );
		
		VKCCategory patentCat = VKCCategorySerializer.retrieveCategory(new Integer(categoryId));
		
		String classifyResult = classifier.classify( patentCat, patentDoc, user);
		if( StringUtils.isEmpty( classifyResult)){
		    classifyResult = classifier.getResultTitle( patentDoc.getName()) + " ohne Ergebnis ;-(";
		}
		
        VKCDocument classifyResultDoc = new VKCDocument();

		classifyResultDoc.setCategoryId( patentDoc.getCategoryId() );
		classifyResultDoc.setPublished( new Date() );
		classifyResultDoc.setLastAccessed( null );
		classifyResultDoc.setLastAccessorId( null );
		classifyResultDoc.setLastChanged( new Date() );
		classifyResultDoc.setLastChangerId( user.getUserId() );
		
        classifyResultDoc.setPublisherId( user.getUserId());
		classifyResultDoc.setTitle( classifier.getResultTitle( patentDoc.getName()) );
		
		classifyResultDoc.setName( classifier.getResultFilename(patentDoc.getName()) );
		classifyResultDoc.setArchiveId( WebShare.archive.store( classifyResult.getBytes() ) );
		classifyResultDoc.setDocSize( new Long(classifyResult.getBytes().length ));
        classifyResultDoc.setZipped( new Integer( 0 ) );
		classifyResultDoc.setDocumentType( VKCDocumentTypeSerializer.getDocumentTypeByExtension( "TXT" ) );
		
		VKCDynaAttribute a = new VKCDynaAttribute();
		a.setDynaAttrId( new Integer( -1 ) );
		a.setName( SharkService.ATTR_PATENT_RELEVANT_LITERATURE);
		a.setValue( "false" );
		
		classifyResultDoc.addDynaAttribute(a);
		
		VKCDocumentSerializer.saveDocument(classifyResultDoc, false, false);

		return classifyResultDoc.getDocumentId().toString();
    }


    /**
     * Liefert zu dem übergebenen Dokument das StdT-Dokument
     * (In Zukunft evtl. geschickter machen: Sot-Attr enthält ID zum dokument...)
     * @param patentDoc
     * @return null, falls kein StdT dokument gefunden
     */
    public static final VKCDocument getStdTDocument(VKCDocument patentDoc) throws DBException{
        VKCCategory thisPatentCat = patentDoc.getCategory();
        
        for( Iterator it = thisPatentCat.getDocuments().iterator(); it.hasNext();){
            VKCDocument doc = (VKCDocument)it.next();
            if(doc.hasDynaAttribute( SharkService.ATTR_STATE_OF_THE_ART_DOC))
                return doc;
        }
        return null;
        
    }


    /**
     * @param sectionEnds
     * @return
     */
     public static final Set getSectionEndPhrases(String sectionEnds) {
    
         if(StringUtils.isEmpty(sectionEnds)){
             return null;
         }
         
        Set s = new HashSet();
        String[] ss = sectionEnds.split(";");
        for (int i = 0; i < ss.length; i++) {
            s.add(ss[i].trim());
            
        }
        
        return s;
    }


    /**
     * Gibt die "PatentApplicationCapable"-Kategorie
     * für ein gegebenes Dokument aus der Kategorie "Neuzugänge"
     * 
     * @param patentDocInIncomingCat
     * @return die "PatentApplicationCapable"-Kategorie
     */
    public static final VKCCategory getPatentsCapableCategory(VKCDocument patentDocInIncomingCat) 
    	throws DBException{
        
        Integer incomingCatId = CategoryUtils.getParentCategoryId(
                					patentDocInIncomingCat.getCategoryId());
        
        return VKCCategorySerializer.retrieveCategory(
                	CategoryUtils.getParentCategoryId(incomingCatId));
    }

 
    /**
     * Ändert das Klassifikationsergebnis dahingehend, dass
     * als Ergebniss nur die Elternkategorien der aktuellen
     * Ergebnisskategorie auftauchen.
     * 
     * @param results
     * @return
     * @throws DBException
     */
    public static final Collection normResultsToParentCategory( Collection results )
    	throws DBException {
        
        Map catIdsCounts = new HashMap();
        Map filteredResults = new HashMap();
        
        for (Iterator iter = results.iterator(); iter.hasNext();) {
            ClassifyResultEntry entry = (ClassifyResultEntry) iter.next();
            entry.setCategoryId(
              CategoryUtils.getParentCategoryId( new Integer(entry.getCategoryId())).toString());
            
            Integer count = (Integer)catIdsCounts.get(entry.getCategoryId());
            if(count == null ){
                catIdsCounts.put( entry.getCategoryId(), new Integer(1));
            }else{
                catIdsCounts.put( entry.getCategoryId(), new Integer(count.intValue()+1));
            }
            
            ClassifyResultEntry fEntry = (ClassifyResultEntry)filteredResults.get(entry.getCategoryId());
            if(fEntry == null){
                filteredResults.put(entry.getCategoryId(), entry);
            }else{
                fEntry.setScore( fEntry.getScore()+ entry.getScore());
            }
            
        }
        
        Collection finalResults = filteredResults.values();
        for (Iterator iter = finalResults.iterator(); iter.hasNext();) {
            ClassifyResultEntry element = (ClassifyResultEntry) iter.next();
            element.setScore( element.getScore()/ ((Integer)catIdsCounts.get(element.getCategoryId())).intValue());
        }
        
        return finalResults;
    }
}
    
