[Biojava-l] Remote Locations

Cox, Greg gcox@netgenics.com
Mon, 5 Feb 2001 14:36:58 -0500


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01C08FAB.0101F920
Content-Type: text/plain;
	charset="iso-8859-1"

I plugged some new data into the genbank and embl parsers, and there's a
slight problem.  A location like "join(L41624.1:2858..5660,1..419)" is valid
and refers to a different sequence, L41624.  I've coded up a new location
type, RemoteLocation to handle this case, but I want some feedback before
committing it.  

	 I've attached my code, but the big problem I see is that
RemoteLocation implements Location, and contains a Location.  I've dealt
with this recursive inheritance before and not enjoyed the experience.  The
other option, inheriting from a concrete location, begs the question of
which one.  

	The other problem I see is that if there are two locations, both
from 1..100 on different sequences, calling
remoteLocation.equals(localLocation) will return false because
remoteLocation knows to check if the parameter is on the right sequence.
But localLocation.equals(remoteLocation) will return true because when
localLocation was coded, remoteLocations didn't exist.  The hack around this
is to do an instanceof for RemoteLocation, but I hope there's a better way.


	Any input is appreciated.  Remember, this is code YOU have to
maintain!

Greg Cox

 <<RemoteLocation.java>> 
 <<RemoteLocation.java>> 

------_=_NextPart_000_01C08FAB.0101F920
Content-Type: application/octet-stream;
	name="RemoteLocation.java"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="RemoteLocation.java"

/*
 *                    BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 *
 */

package org.biojava.bio.symbol;

import java.util.*;
import java.io.*;
import java.lang.reflect.*;

import org.biojava.utils.*;
import org.biojava.bio.*;

/**
 * A biological location on a sequence other than the one it's attached =
to.
 * For example, in a Genbank feature who's location is of the form
 * L41624.1:2858.
 * <P>
 * The location will contain some symbols between getMin and getMax =
inclusive.
 * It is not required to contain all locations within this range. It is =
meant
 * to contain getMin or getMax. In the event that an operation would =
produce an
 * invalid or nonsensical range, empty should be returned.
 * </p>
 *
 * <p>
 * Location objects are <strong>always</strong> immutable.
 * </p>
 *
 * @author Greg Cox
 */
public class RemoteLocation implements Location
{
	// Member variables
	private Location mLocation;
	private String mAccessionNumber;

	// Constructor
	public RemoteLocation(Location theLocation, String theAccessionNumber)
	{
		mLocation =3D theLocation;
		mAccessionNumber =3D theAccessionNumber;
	}

	// Interface methods
	public int getMin()
	{
		return this.getLocation().getMin();
	}

	public int getMax()
	{
		return this.getLocation().getMax();
	}

	public boolean overlaps(Location l)
	{
		boolean isOverlap =3D false;
		// Overlap is false if the locations are on different sequences
		if(this.isSameSequence(l))
		{
			isOverlap =3D =
this.getLocation().overlaps(((RemoteLocation)l).getLocation());
		}
		return isOverlap;
	}

	public boolean contains(Location l)
	{
		boolean doesContain =3D false;
		// Contains is false if the locations are on different sequences
		if(this.isSameSequence(l))
		{
			doesContain =3D =
this.getLocation().contains(((RemoteLocation)l).getLocation());
		}
		return doesContain;
	}

	public boolean contains(int p)
	{
		return this.getLocation().contains(p);
	}

	public boolean equals(Object l)
	{
		boolean doesEqual =3D false;
		// Equality is false if the locations are on different sequences
		if(l instanceof RemoteLocation)
		{
			String lAccessionNumber =3D =
((RemoteLocation)l).getAccessionNumber();
			if(this.getAccessionNumber().equals(lAccessionNumber))
			{
				doesEqual =3D =
this.getLocation().equals(((RemoteLocation)l).getLocation());
			}
		}
		return doesEqual;
	}

	public Location intersection(Location l)
	{
		Location theIntersection =3D Location.empty;
		// The intersection is empty if the locations are on different =
sequences
		if(this.isSameSequence(l))
		{
			theIntersection =3D =
this.getLocation().intersection(((RemoteLocation)l).getLocation());
		}
		return theIntersection;
	}

	public Location union(Location l)
	{
		Location returnLocation;
		if(this.isSameSequence(l))
		{
			Location componentLocation =3D =
this.getLocation().union(((RemoteLocation)l).getLocation());
			returnLocation =3D new RemoteLocation(componentLocation, =
this.getAccessionNumber());
		}
		else
		{
			// If the locations are on different sequences, the union is both
			// of them
			List LocationList =3D new ArrayList();
			LocationList.add(this.getLocation());
			LocationList.add(l);
			returnLocation =3D new CompoundLocation(LocationList);
		}
		return returnLocation;
	}

	public SymbolList symbols(SymbolList seq)
	{
		throw new UnsupportedOperationException();
	}

	public Location translate(int dist)
	{
		throw new UnsupportedOperationException();
	}

	public boolean isContiguous()
	{
		return this.getLocation().isContiguous();
	}

	public Iterator blockIterator()
	{
		return this.getLocation().blockIterator();
	}

	// Public methods
	/**
	 * Returns the accession number of the sequence this location refers =
to
	 *
	 * @return String The accession number
	 */
	public String getAccessionNumber()
	{
		return mAccessionNumber;
	}

	/**
	 * Returns the location this location refers to
	 *
	 * @return Location The location
	 */
	public Location getLocation()
	{
		return mLocation;
	}

	// Private Methods
	/**
	 * Returns true is the parameter location refers to the same sequence =
as
	 * this one and false otherwise
	 *
	 * @param theLocation The location to check the accession number of
	 * @return boolean True if the locations refer to the same sequence =
and
	 * false otherwise
	 */
	private boolean isSameSequence(Location theLocation)
	{
		boolean areSameSequence =3D false;
		// Equality is false if the locations are on different sequences
		if(theLocation instanceof RemoteLocation)
		{
			areSameSequence =3D =
this.getAccessionNumber().equals(((RemoteLocation)theLocation).getAccess=
ionNumber());
		}
		return areSameSequence;
	}
}

------_=_NextPart_000_01C08FAB.0101F920
Content-Type: application/octet-stream;
	name="RemoteLocation.java"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="RemoteLocation.java"

/*
 *                    BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 *
 */

package org.biojava.bio.symbol;

import java.util.*;
import java.io.*;
import java.lang.reflect.*;

import org.biojava.utils.*;
import org.biojava.bio.*;

/**
 * A biological location on a sequence other than the one it's attached =
to.
 * For example, in a Genbank feature who's location is of the form
 * L41624.1:2858.
 * <P>
 * The location will contain some symbols between getMin and getMax =
inclusive.
 * It is not required to contain all locations within this range. It is =
meant
 * to contain getMin or getMax. In the event that an operation would =
produce an
 * invalid or nonsensical range, empty should be returned.
 * </p>
 *
 * <p>
 * Location objects are <strong>always</strong> immutable.
 * </p>
 *
 * @author Greg Cox
 */
public class RemoteLocation implements Location
{
	// Member variables
	private Location mLocation;
	private String mAccessionNumber;

	// Constructor
	public RemoteLocation(Location theLocation, String theAccessionNumber)
	{
		mLocation =3D theLocation;
		mAccessionNumber =3D theAccessionNumber;
	}

	// Interface methods
	public int getMin()
	{
		return this.getLocation().getMin();
	}

	public int getMax()
	{
		return this.getLocation().getMax();
	}

	public boolean overlaps(Location l)
	{
		boolean isOverlap =3D false;
		// Overlap is false if the locations are on different sequences
		if(this.isSameSequence(l))
		{
			isOverlap =3D =
this.getLocation().overlaps(((RemoteLocation)l).getLocation());
		}
		return isOverlap;
	}

	public boolean contains(Location l)
	{
		boolean doesContain =3D false;
		// Contains is false if the locations are on different sequences
		if(this.isSameSequence(l))
		{
			doesContain =3D =
this.getLocation().contains(((RemoteLocation)l).getLocation());
		}
		return doesContain;
	}

	public boolean contains(int p)
	{
		return this.getLocation().contains(p);
	}

	public boolean equals(Object l)
	{
		boolean doesEqual =3D false;
		// Equality is false if the locations are on different sequences
		if(l instanceof RemoteLocation)
		{
			String lAccessionNumber =3D =
((RemoteLocation)l).getAccessionNumber();
			if(this.getAccessionNumber().equals(lAccessionNumber))
			{
				doesEqual =3D =
this.getLocation().equals(((RemoteLocation)l).getLocation());
			}
		}
		return doesEqual;
	}

	public Location intersection(Location l)
	{
		Location theIntersection =3D Location.empty;
		// The intersection is empty if the locations are on different =
sequences
		if(this.isSameSequence(l))
		{
			theIntersection =3D =
this.getLocation().intersection(((RemoteLocation)l).getLocation());
		}
		return theIntersection;
	}

	public Location union(Location l)
	{
		Location returnLocation;
		if(this.isSameSequence(l))
		{
			Location componentLocation =3D =
this.getLocation().union(((RemoteLocation)l).getLocation());
			returnLocation =3D new RemoteLocation(componentLocation, =
this.getAccessionNumber());
		}
		else
		{
			// If the locations are on different sequences, the union is both
			// of them
			List LocationList =3D new ArrayList();
			LocationList.add(this.getLocation());
			LocationList.add(l);
			returnLocation =3D new CompoundLocation(LocationList);
		}
		return returnLocation;
	}

	public SymbolList symbols(SymbolList seq)
	{
		throw new UnsupportedOperationException();
	}

	public Location translate(int dist)
	{
		throw new UnsupportedOperationException();
	}

	public boolean isContiguous()
	{
		return this.getLocation().isContiguous();
	}

	public Iterator blockIterator()
	{
		return this.getLocation().blockIterator();
	}

	// Public methods
	/**
	 * Returns the accession number of the sequence this location refers =
to
	 *
	 * @return String The accession number
	 */
	public String getAccessionNumber()
	{
		return mAccessionNumber;
	}

	/**
	 * Returns the location this location refers to
	 *
	 * @return Location The location
	 */
	public Location getLocation()
	{
		return mLocation;
	}

	// Private Methods
	/**
	 * Returns true is the parameter location refers to the same sequence =
as
	 * this one and false otherwise
	 *
	 * @param theLocation The location to check the accession number of
	 * @return boolean True if the locations refer to the same sequence =
and
	 * false otherwise
	 */
	private boolean isSameSequence(Location theLocation)
	{
		boolean areSameSequence =3D false;
		// Equality is false if the locations are on different sequences
		if(theLocation instanceof RemoteLocation)
		{
			areSameSequence =3D =
this.getAccessionNumber().equals(((RemoteLocation)theLocation).getAccess=
ionNumber());
		}
		return areSameSequence;
	}
}

------_=_NextPart_000_01C08FAB.0101F920--