All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javatools.parsers.PositionTracker Maven / Gradle / Ivy

Go to download

Structr is an open source framework based on the popular Neo4j graph database.

The newest version!
/**
 * Copyright (C) 2010-2016 Structr GmbH
 *
 * This file is part of Structr .
 *
 * Structr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Structr 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Structr.  If not, see .
 */
package javatools.parsers;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * This class is part of the Java Tools (see
 * http://mpii.de/yago-naga/javatools). It is licensed under the Creative
 * Commons Attribution License (see http://creativecommons.org/licenses/by/3.0)
 * by the YAGO-NAGA team (see http://mpii.de/yago-naga).
 * 
 * This class implements position change trackers that keep track of position
 * changes within a String, e.g. caused through normalization etc.
 * This allows for instance, given a position int the normalized string
 * to get the corresponding position in the original non-normalized string 
 * 
 *
 * 
 * backward position tracker - 
 * tracking several replacement/text changes allowing to trace a position in the modified 
 * text back to the corresp. position in the original text 
 * for the other direction see ForwardPositionTracker 
 * 
 * @author smetzger */
public class PositionTracker {
	
	
	private SortedMappositionMap;
	private SortedMappositionChanges;
	private SortedMapold2NewMap;
	private int accumulatedModifier=0;
	  
	public PositionTracker(){
		positionMap=new TreeMap();
		positionChanges=new TreeMap();
		old2NewMap=new TreeMap();		     
	}
	
	  
	public void addPositionChange(int pos, int modifier){
	      if(modifier!=0){	    	  
          int oldModifier=0;         
	    	  old2NewMap.put(pos, modifier);
          accumulatedModifier+=modifier;
          if(positionChanges.containsKey(pos+accumulatedModifier))
            oldModifier=positionChanges.get(pos+accumulatedModifier);
	    	  positionChanges.put(pos+accumulatedModifier,modifier*-1+oldModifier);	    	  
	      }		  
	}

	  
	  
	/** Closes the current changing run by Merging new position changes into the existing position change map
   *  after each round (one round=consecutive changes along the text) you need to call closeRun() before submitting more position changes from a new round,
   *  i.e. whenever you passed the string to be modified once call closeRun() before starting to run over the string again with more replacements
	 * Do this every time you ran once over the text making changes to be tracked*/ 
	public void closeRun() {
		if(positionChanges.isEmpty())
		  return;
	  		
		  
		SortedMap temp=positionChanges;
		 
		//adapt old positions to new mapping
		while(!positionMap.isEmpty()){
		  Integer key=positionMap.firstKey();
	  	  Collection modifiers=old2NewMap.headMap(key+1).values();
	  	  Integer newposition=key;    	
	  	  for(Iterator it=modifiers.iterator(); it.hasNext(); newposition+=it.next()){}
	  	  Integer value=positionMap.get(key);
	  	  if(positionChanges.containsKey(newposition))
	  		  value+=positionChanges.get(newposition);
	  	  positionChanges.put(newposition, value);
	  	  positionMap.remove(key);
		}

		positionChanges=positionMap;
		positionMap=temp;
		old2NewMap.clear();
		accumulatedModifier=0;
		return;
	}
	  
	  
	  
	  
	/** Merges new position changes (given with the inversed old2new mapping) into the existing position change map*/ 
/*	private void addPositionMappings(SortedMap newPosChanges, 
	   		SortedMap old2NewMap) {
	  
		
		TreeMap newMap=new TreeMap();
		 
		//adapt old positions to new mapping
		while(!positionMap.isEmpty()){
		  Integer key=positionMap.firstKey();
	  	  Collection modifiers=old2NewMap.headMap(key+1).values();
	  	  Integer newposition=key;    	
	  	  for(Iterator it=modifiers.iterator(); it.hasNext(); newposition+=it.next()){}
	  	  Integer value=positionMap.get(key);
	  	  if(newMap.containsKey(newposition))
	  		  value+=newMap.get(newposition);
	  	  newMap.put(newposition, value);
	  	  positionMap.remove(key);
		}
		while(!newPosChanges.isEmpty()){
		  Integer key=newPosChanges.firstKey();
		  Integer value=newPosChanges.get(key);
		  if(newMap.containsKey(key))
		     value+=newMap.get(key);
		  newMap.put(key, value);
		  newPosChanges.remove(key);						
		}
		positionMap=newMap;
		old2NewMap.clear();
		return;
	}
	  */
	  
	public Integer translatePosition(Integer pos) {
		SortedMap headMap=positionMap.headMap(pos+1);
		  Integer modifier=0;    	
		  for(Iterator it=headMap.values().iterator(); it.hasNext(); modifier+=it.next()){}
/*		  if(headMap.size()>1){      TODO: Possible Optimization if we assume positions are asked in ascending order
			  headMap.clear();
			  posMap.put(pos, modifier);
		  }*/ 
		  return pos+modifier;		  
	}
  

    

  
  
  
  
  
  
  
  /** forward position change tracking - keeping track of several rounds of text modifications allowing to trace a position in the original
   *  text along the modifications to the corresp. position in the modified text 
   *  after each round (one round=consecutive changes along the text) you need to call closeRun() before submitting more position changes from a new round,
   *  i.e. whenever you passed the string to be modified once call closeRun() before starting to run over the string again with more replacements
   *  REMARK: NOT TESTED WITH MORE THAN ONE ROUND! may be ERRORNOUS with multiple rounds -> use with care (works with a single round though)
   * @author smetzger
   *
   */
  public static class ForwardPositionTracker {
    
    
    private SortedMappositionMap;
    private SortedMappositionChanges;
    //private SortedMapnew2OldMap;
    private PositionTracker new2OldTracker=null;
  //  private int accumulatedModifier=0;
      
    public ForwardPositionTracker(){
      positionMap=new TreeMap();
      positionChanges=new TreeMap();
     // new2OldMap=new TreeMap();
      new2OldTracker=new PositionTracker();
     
    }
    
      
    public void addPositionChange(int pos, int modifier){
          if(modifier!=0){                                         
            positionChanges.put(pos,modifier);
  //          accumulatedModifier+=modifier;
            /*if(new2OldMap.containsKey(pos+accumulatedModifier))
              oldModifier=new2OldMap.get(pos+accumulatedModifier);
            new2OldMap.put(pos+accumulatedModifier, -1*modifier+oldModifier);                        
          }     */
            new2OldTracker.addPositionChange(pos, modifier);
          }
    }
    




      
      
    /** Closes the current changing run by Merging new position changes into the existing position change map
     * Do this every time you ran once over the text making changes to be tracked*/ 
    public void closeRun() {
      if(positionChanges.isEmpty())
        return;

      
      for(Map.Entry change:positionChanges.entrySet()){
        Integer positionInOrigStream=new2OldTracker.translatePosition(change.getKey());
        if(positionMap.containsKey(positionInOrigStream))
          positionMap.put(positionInOrigStream, change.getValue()+positionMap.get(positionInOrigStream));
        else
          positionMap.put(positionInOrigStream, change.getValue());
      }
       
      positionChanges.clear();
//      accumulatedModifier=0;
      new2OldTracker.closeRun();
        
      return;
    }
      
    
      
    /** tells whether a position in the original stream has been cut away by some change operation, 
     *  such that translating it usually would make not to much sense
     *  @return true, iff the given position has been cut away, false otherwise (i.e. false if it should be mappable)
     *  TODO: current version ONLY WORKS SECURELY WHEN THERE IS ONLY ONE POSITION CHANGE RUN WITHOUT OVERLAPPING CHANGES!
     *  as soon as there are more than one change runs, or changes that overlap, we would need to check all following changes instead of only the next one */
    public boolean hasBeenCutAway(Integer pos){
        SortedMap tailMap=positionMap.tailMap(pos+1);
        if(tailMap.isEmpty())
          return false;
        Integer key=tailMap.firstKey();
        Integer modifier=tailMap.get(key);
        if(modifier<0 && key+modifier<=pos )
          return true;
        else 
          return false;
        /* this does not work for the general case (had it the wrong way aroung), but can be used to implement it
        Integer key=null;
        Iterator it=tailMap.keySet().iterator();
        while(it.hasNext()){
          key=it.next();
          Integer mod=tailMap.get(key);
          if(mod<0 && key-mod>=pos)
            return true;
        }  
        return false;*/
      }
      
    public Integer translatePosition(Integer pos) {
      SortedMap headMap=positionMap.headMap(pos+1);
        Integer modifier=0;     
        for(Iterator it=headMap.values().iterator(); it.hasNext(); modifier+=it.next()){}
  /*      if(headMap.size()>1){      Optimization if we assume positions are asked in ascending order
          headMap.clear();
          posMap.put(pos, modifier);
        }*/ 
        return pos+modifier;      
    }
    
    /** also handles positions inside text parts that have been cut out properly 
     * 
     *  TODO: current version ONLY WORKS SECURELY WHEN THERE IS ONLY ONE POSITION CHANGE RUN WITHOUT OVERLAPPING CHANGES!
     *  as soon as there are more than one change runs, or changes that overlap, we would need to check all following changes instead of only the next one */
    public Integer translatePositionExactly(Integer pos) {

      SortedMap tailMap=positionMap.tailMap(pos+1);
      if(tailMap.isEmpty())
        return translatePosition(pos);
      else{
        Integer key=tailMap.firstKey();
        Integer modifier=tailMap.get(key);
        return translatePosition(Math.min(pos,key+modifier));
      }
      
/*        
 *        That version does it the wrong way around
 *        SortedMap headMap=positionMap.headMap(pos+1);
          Integer modifier=0;     
          Integer key=null, value=null;
          Iterator it=headMap.keySet().iterator();
          while(it.hasNext()){
            key=it.next();
        	  value=headMap.get(key);
        	  if(value<0)
        		  modifier+=Math.max(key-pos, value);
          }*/
    /*      if(headMap.size()>1){      Optimization if we assume positions are asked in ascending order
            headMap.clear();
            posMap.put(pos, modifier);
          }
          return pos+modifier;    */ 
            
      }

  }
  
  
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy