Skip to content
Snippets Groups Projects
Commit d3117e50 authored by felmer's avatar felmer
Browse files

introduce spreadsheet location parsing (will actually be used for well...

introduce spreadsheet location parsing (will actually be used for well locations on a screening plate)

SVN: 5728
parent 80f3d1cb
No related branches found
No related tags found
No related merge requests found
/*
* Copyright 2008 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.common.geometry;
/**
* Conversion utility functions.
*
* @author Franz-Josef Elmer
*/
public class ConversionUtils
{
private static final int MAX_LETTER_NUMBER = getLetterNumber('Z');
/**
* Parses a spreadsheet location and return a point. The location has to start with one or more
* letters ignoring case. This letter section code the x-coordinate with 'A'=0, 'B'=1, ...,
* 'Z'=25, 'AA'=26, ..., 'AZ'=51, 'BA'=52, 'BB'=53, etc. After the letter section follows
* one or more digits. The code the y-coordinate plus one. That is, one has to subtract 1
* to get the actual value of the returned y-coordinate.
* <p>
* Examples:
* <pre>
* A01 -> x = 0, y = 0
* C7 -> x = 2, y = 6
* AB19 -> x = 27, y = 18
* </pre>
*
* @throws IllegalArgumentException if the location is not a valid one.
*/
public static Point parseSpreadsheetLocation(String spreadsheetLocation)
{
if (spreadsheetLocation == null || spreadsheetLocation.length() == 0)
{
throw new IllegalArgumentException("Unspecified location.");
}
int indexOfFirstDigit = 0;
while (indexOfFirstDigit < spreadsheetLocation.length()
&& Character.isDigit(spreadsheetLocation.charAt(indexOfFirstDigit)) == false)
{
indexOfFirstDigit++;
}
if (indexOfFirstDigit == 0)
{
throw new IllegalArgumentException("Missing letter part of the location: " + spreadsheetLocation);
}
int x = 0;
for (int i = 0; i < indexOfFirstDigit; i++)
{
char letter = spreadsheetLocation.charAt(i);
int digit = getLetterNumber(letter);
if (digit < 0 || digit > MAX_LETTER_NUMBER)
{
throw new IllegalArgumentException("Invalid letter '" + letter + "' in location: " + spreadsheetLocation);
}
x = x * MAX_LETTER_NUMBER + digit;
}
int y;
try
{
y = Integer.parseInt(spreadsheetLocation.substring(indexOfFirstDigit));
} catch (NumberFormatException ex)
{
throw new IllegalArgumentException("Number part of the location is not a number: " + spreadsheetLocation);
}
if (y < 1)
{
throw new IllegalArgumentException("Number part of the location is not a positive number: " + spreadsheetLocation);
}
return new Point(x - 1, y - 1);
}
private static int getLetterNumber(final char ch)
{
return Character.toUpperCase(ch) - 'A' + 1;
}
private ConversionUtils()
{
}
}
/*
* Copyright 2008 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.common.geometry;
/**
* Immutable value object representing a point in the two dimensional raster.
*
* @author Franz-Josef Elmer
*/
public final class Point
{
private final int x;
private final int y;
/**
* Create instance for the specified x- and y-coordinates.
*/
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
/**
* Returns the x coordinate.
*/
public final int getX()
{
return x;
}
/**
* Returns the y coordinate.
*/
public final int getY()
{
return y;
}
//
// Object
//
@Override
public final boolean equals(Object obj)
{
if (obj == this)
{
return true;
}
if (obj instanceof Point == false)
{
return false;
}
final Point point = (Point) obj;
return point.x == x && point.y == y;
}
@Override
public final int hashCode()
{
int hashCode = 17;
hashCode = hashCode * 37 + x;
hashCode = hashCode * 37 + y;
return hashCode;
}
@Override
public final String toString()
{
return "(" + x + "," + y + ")";
}
}
/*
* Copyright 2008 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.common.geometry;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.fail;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
*
*
* @author Franz-Josef Elmer
*/
public class ConversionUtilsTest
{
@DataProvider(name = "valid spreadsheet locations")
public Object[][] provideCorrectData()
{
return new Object[][]
{
{ "A01", 0, 0 },
{ "A1", 0, 0 },
{ "A123", 0, 122 },
{ "B09", 1, 8 },
{ "C23", 2, 22 },
{ "AA1", 26 + 1 - 1, 0 },
{ "ZZ1000", 26 * 26 + 26 - 1, 999 },
{ "B05", 1, 4 },
{ "a01", 0, 0 },
{ "c23", 2, 22 },
{ "zZ1000", 26 * 26 + 26 - 1, 999 } };
}
@Test(dataProvider = "valid spreadsheet locations")
public void testParseSpreadsheetLocationWithValidLocations(String location, int x, int y)
{
assertEquals(new Point(x, y), ConversionUtils.parseSpreadsheetLocation(location));
}
@Test
public void testParseSpreadsheetLocationWithEmptyString()
{
try
{
ConversionUtils.parseSpreadsheetLocation("");
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e)
{
assertEquals("Unspecified location.", e.getMessage());
}
}
@Test
public void testParseSpreadsheetLocationWithOnlyNumbers()
{
try
{
ConversionUtils.parseSpreadsheetLocation("123");
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e)
{
assertEquals("Missing letter part of the location: 123", e.getMessage());
}
}
@Test
public void testParseSpreadsheetLocationWithInvalidLetter()
{
try
{
ConversionUtils.parseSpreadsheetLocation("A?");
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e)
{
assertEquals("Invalid letter '?' in location: A?", e.getMessage());
}
}
@Test
public void testParseSpreadsheetLocationWithInvalidDigitLetter()
{
try
{
ConversionUtils.parseSpreadsheetLocation("A1?");
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e)
{
assertEquals("Number part of the location is not a number: A1?", e.getMessage());
}
}
@Test
public void testParseSpreadsheetLocationWithNonPositiveNumber()
{
try
{
ConversionUtils.parseSpreadsheetLocation("A0");
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e)
{
assertEquals("Number part of the location is not a positive number: A0", e.getMessage());
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment