I have a csvfile
id|name
1|PC
2|Activation
3|USB
public class TESTResult
{
private Long id;
private String name;
private Float score;
// with setters & getters
}
public class TEST
{
private Long id;
private String name;
// with setters & getters
}
public class JobTESTTagger {
private static Version VERSION;
private static CharArraySet STOPWORDS;
private static RewriteMethod REWRITEMETHOD;
private static Float MINSCORE = 0.0001F;
static {
BooleanQuery.setMaxClauseCount(100000);
VERSION = Version.LUCENE_44;
STOPWORDS = StopAnalyzer.ENGLISH_STOP_WORDS_SET;
REWRITEMETHOD = MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE;
}
public static ArrayList<TESTResult> searchText(String text, String keyId,
List<TEST> TESTs) {
ArrayList<TESTResult> results = new ArrayList<TESTResult>();
MemoryIndex index = new MemoryIndex();
EnglishAnalyzer englishAnalyzer = new EnglishAnalyzer(VERSION,STOPWORDS);
QueryParser parser = new QueryParser(VERSION, "text", englishAnalyzer);
parser.setMultiTermRewriteMethod(REWRITEMETHOD);
index.addField("text", text, englishAnalyzer);
for (int i = 0; i < TESTs.size(); i++) {
TEST TEST = TESTs.get(i);
String criteria = "\"" + TEST.getName().trim() + "\"";
if (criteria == null || criteria.isEmpty())
continue;
criteria = criteria.replaceAll("\r", " ");
criteria = criteria.replaceAll("\n", " ");
try {
Query query = parser.parse(criteria);
Float score = index.search(query);
if (score > MINSCORE) {
int result = new TESTResult(TEST.getId(), TEST.getName(),score);
results.add(result);
}
} catch (ParseException e) {
System.out.println("Could not parse article.");
}
}
return results;
}
public static void main(String[] args) {
ArrayList<TESTResult> testresults = searchText(text, keyId, iths);
CsvReader reader = new CsvReader("C:\a.csv");
reader.setDelimiter('|');
reader.readHeaders();
List<TEST> result = new ArrayList<TEST>();
while (reader.readRecord()) {
Long id = Long.valueOf(reader.get("id").trim());
String name = reader.get("name").trim();
TEST concept = new TEST(id, name);
result.add(concept);
}
String text = "These activities are good. I have a good PC in my house.";
}
I am matching 'activities' to Activation. How is it possible. Can anybody tell me how Lucene matches the words.
Thanks
R
EnglishAnalyzer, along with most language-specific analyzers, uses a stemmer. This means that it reduces terms to a stem (or root) of the term, in order to attempt to match more loosely. Mostly this works well, removing suffixes and matching up derived words to a common root. So when I search for "fish", I also find "fished", "fishing" and "fishes".
In this case though, both "activities" and "activation" both reduce to the root of "activ", resulting in the match you are seeing. Another example: "organ", "organic" and "organize" all have the common stem "organ".
You can stem or not, neither approach is perfect. If you don't stem you'll miss relevant results. If you do, you'll hit some odd irrelevant results.
To deal with specific problematic cases, you can define a stemmer exclusion set in EnglishAnalyzer to prevent stemming just on those specific problematic terms. In this case, I would think of "activation" as the probable term to prevent stemming on, though you could go either way. So I could do something like:
CharArraySet stemExclusionSet = new CharArraySet(VERSION, 1, true);
stemExclusionSet.add("activation");
EnglishAnalyzer englishAnalyzer = new EnglishAnalyzer(VERSION, STOPWORDS, stemExclusionSet);
Related
What I'm trying to do: I have a set of golf club objects(~60 clubs). Depending on the club name and club level(1-10 levels), each one will have a different maxmultiplier and minmultiplier value associated with it that I will need to perform calculations.
What I've thought about:
Using switch statement for the club levels and a hashmap to pair the club name with an array of the multipliers in order to retrieve the correct values. Issue I have with this would be that I would have to create ~60 separate 2item arrays for the multipliers. Thought about 2d arrays and so forth but I'm at the point where it feels like I'm going in circles. I know I CAN get it to work through brute force but I'm trying to work on efficiency. Is there a way to set this up in a localized way(table-like structure) that would make it easy to retrieve?
Things to Note: Java is my first language,I'm trying to learn, I'm at the skill level where I can MAKE things work but am transitioning into learning best practices. So for answers If we could stick with basic/intermediate java ideas that would be appreciated. But after I get it working next step will be implementing serializable to store data outside the program and learning that, followed by storing information in a SQL database which ultimately seems the easiest in my mind using a table.
Here is some of my code:
/*
* Creates all the clubs to be used in the app
*/
public ClubSet() {
clubMap = new HashMap<String, String[]>(100, (float) 0.8);
clubMap.put("DRIVER", driverArray);//all the club names of driver type
clubMap.put("WOOD", woodArray);
clubMap.put("LONG", longArray);
clubMap.put("SHORT", shortArray);
clubMap.put("WEDGE", wedgeArray);
clubMap.put("ROUGH", roughArray);
clubMap.put("SAND", sandArray);
for (HashMap.Entry<String, String[]> entry : clubMap.entrySet()) {
for (String clubName : entry.getValue()) {
Club club = new Club(entry.getKey(), clubName);
this.put(club, club.getClubType());
}
}
}
/*
* Returns a set of all clubs according to clubtypre(e.g. Driver,Wood,Long
* Iron,etc)
*/
public HashSet<Club> getClubSet(String clubType) {
HashSet<Club> clubSet = new HashSet<Club>();
if (this.containsValue(clubType)) {
for (HashMap.Entry<Club, String> entry : this.entrySet()) {
if (entry.getValue().equalsIgnoreCase(clubType)) {
clubSet.add(entry.getKey());
}
}
}
return clubSet;
}
}
public class Club {
private String clubType;
private String clubName;
private int level;
private ImageIcon imageIcon;
private String rarity;
private double maxMultiplier;
private double minMultiplier;
private HashMap<String, String[]> rarityMap;
private final String[] starterArray = new String[] { "BEGINNER DRIVER", "BEGINNER WOOD", "BEGINNER LONG",
"BEGINNER SHORT", "BEGINNER WEDGE", "BEGINNER ROUGH", "BEGINNER SAND" };
private final String[] commonArray = new String[] { "ROCKET", "QUARTERBACK", "VIPER", "SNIPER", "BACKBONE",
"SATURN", "RUNNER", "CLAW", "DART", "SKEWER", "MACHETE", "DESERT STORM", "SAND LIZARD" };
private final String[] rareArray = new String[] { "EXTRA MILE", "ROCK", "BIG DAWG", "GUARDIAN", "GOLIATH",
"GRIZZLY", "APACHE", "THORN", "HORNET", "DOWN-IN-ONE", "RAPIER", "ROUGHCUTTER", "RAZOR", "NIRVANA",
"MALIBU", "HOUDINI" };
private final String[] epicArray = new String[] { "APOCALYPSE", "BIG TOPPER", "THOR'S HAMMER", "HORIZON",
"CATACLYSM", "HAMMERHEAD", "GRIM REAPER", "B52", "TSUNAMI", "KINGFISHER", "FALCON", "FIREFLY", "BOOMERANG",
"ENDBRINGER", "JUNGLIST", "OFF ROADER", "AMAZON", "CASTAWAY", "SAHARA", "SPITFIRE" };
public Club() {
this.clubType = null;
this.clubName = null;
this.level = 1;
rarity = null;
// maxMultiplier = 0;
// minMultiplier = 0;
}
public Club(String clubType, String clubName) {
this.clubName = clubName;
this.clubType = clubType;
this.level = 1;
if (Arrays.asList(starterArray).contains(clubName)) {
this.rarity = "STARTER";
} else if (Arrays.asList(commonArray).contains(clubName)) {
this.rarity = "COMMON";
} else if (Arrays.asList(rareArray).contains(clubName)) {
this.rarity = "RARE";
} else if (Arrays.asList(epicArray).contains(clubName)) {
this.rarity = "EPIC";
}
// setMultipliers(clubName);
}
I'm trying to read csv file that contains strings both quoted and not.
If string is quoted, it should save it's quote chars.
Beside that, if string contains comma, it should not be split.
I've tried multiple ways but nothing works as of now.
Current test data:
"field1 (with use of , we lose the other part)",some description
field2,"Dear %s, some text"
Getting 1st field of mapped bean
Expected result:
"field1 (with use of , we lose the other part)"
field2
Current result:
"field1 (with use of
field2
Here is the code:
public class CsvToBeanReaderTest {
#Test
void shouldIncludeDoubleQuotes() {
String testData =
"\"field1 (with use of , we lose the other part)\",some description\n"
+
"field2,\"Dear %s, some text\"";
RFC4180ParserBuilder rfc4180ParserBuilder = new RFC4180ParserBuilder();
rfc4180ParserBuilder.withQuoteChar(ICSVWriter.NO_QUOTE_CHARACTER);
ICSVParser rfc4180Parser = rfc4180ParserBuilder.build();
CSVReaderBuilder builder = new CSVReaderBuilder(new StringReader(testData));
CSVReader reader = builder
.withCSVParser(rfc4180Parser)
.build();
List<TestClass> result = new CsvToBeanBuilder<TestClass>(reader)
.withType(TestClass.class)
.withEscapeChar('\"')
.build()
.parse();
result.forEach(testClass -> System.out.println(testClass.getField1()));
}
private List<TestClass> readTestData(String testData) {
return new CsvToBeanBuilder<TestClass>(new StringReader(testData))
.withType(TestClass.class)
.withSeparator(',')
.withSkipLines(0)
.withIgnoreEmptyLine(true)
.build()
.parse();
}
public static final class TestClass {
#CsvBindByPosition(position = 0)
private String field1;
#CsvBindByPosition(position = 1)
private String description;
public String toCsvFormat() {
return String.join(",",
field1,
description);
}
public String getField1() {
return field1;
}
}
}
I've found out that if I comment or remove rfc4180ParserBuilder.withQuoteChar(ICSVWriter.NO_QUOTE_CHARACTER); the string will be parsed correctly, but I will lose the quote char which should not be lost. Is there any suggestions what can be done? (I would prefer not to switch on other csv libraries)
The overall project is creating a system manager for airports. It keeps track of airports, flights, seating sections, seats and other relevent info for each of those catagories. The initial system is set up by importing from a file that's formatted a certain way. I'm having problems parsing the file properly to set up the initial system. the data is parsed from the file and used as method parameters to create the objects: Airport, Airline, Flight, FlightSection, and Seat.
the formatting is:
[list-of-airport-codes] {list-of-airlines}
list-of-airport-codes ::= comma-separated strings
list-of-airlines ::= airline-name1[flightinfo-list1], airline-name2[flightinfo-list2], airlinename3[flightinfo-list3], …
flightinfo-list ::= flightID1|flightdate1|originAirportCode1|destinationAirportCode1[flightsectionlist1], flightID2|flightdate2|originAirportCode2|destinationAirportCode2[flightsection-list2], …
flightdate ::= year, month, day-of-month, hours, minutes
flightsection-list ::= sectionclass: seat-price: layout: number-of-rows, …
sectionclass ::= F, B, E (for first class, business class, economy class)
layout ::= S, M, W (different known seating layouts)
example:
[DEN,NYC,SEA,LAX]{AMER[AA1|2018,10,8,16,30|DEN|LAX[E:200:S:4,F:500:S:2],
AA2|2018,8,9,7,30|LAX|DEN[E:200:S:5,F:500:S:3], …], UNTD[UA21|2018,11,8,12,30|NYC|SEA[E:300:S:6,F:800:S:3], UA12|2018,8,9,7,30|SEA|DEN[B:700:S:5, F:1200:S:2], …], FRONT[…], USAIR[…]}
I tried brute forcing it using a combination of delimiters and while loops. The code successfully creates the Airports, first Airline and Flighsections, but when it gets to creating the second airline it crashes, because i'm not looping properly, and having a hard time getting it right. My code for it as of now, is a mess, and if you're willing to look at it, I would appreciate any constructive input. My question is what would be a better way to approach this? A different design approach? Maybe a smarter way to use the delimiters?
Thanks in advance for your help!!
here's what i've tried.
private void readFile(File file){
System.out.println("reading file");
Scanner tempScan;
String result;
String temp = "";
scan.useDelimiter("\\[|\\{");
try{
// AIRPORTS
result = scan.next();
tempScan = new Scanner(result);
tempScan.useDelimiter(",|\\]");
while(tempScan.hasNext()){
temp = tempScan.next();
sysMan.createAirport(temp);
}
tempScan.close();
/* AIRLINE
* FLIGHT
* FLIGHTSECTION
*/
do{
// AIRLINE (loop<flight & fsection>)
result = scan.next();
sysMan.createAirline(result);
// FLIGHT
result = scan.next();
tempScan = new Scanner(result);
do{
tempScan.useDelimiter(",|\\|");
ArrayList flightInfo = new ArrayList();
while(tempScan.hasNext()){
if(tempScan.hasNextInt()){
flightInfo.add(tempScan.nextInt());
} else {
flightInfo.add(tempScan.next());
}
}
tempScan.close();
sysMan.createFlight(sysMan.getLastAddedAirline(),(String)flightInfo.get(0), (int)flightInfo.get(1), (int)flightInfo.get(2), (int)flightInfo.get(3), (int)flightInfo.get(4), (int)flightInfo.get(5), (String)flightInfo.get(6), (String)flightInfo.get(7));
// FLIGHTSECTION (loop<itself>)
result = scan.next();
tempScan = new Scanner(result);
tempScan.useDelimiter(",|:|\\]");
ArrayList sectInfo = new ArrayList();
int i = 1;
while(!temp.contains("|")){
if(tempScan.hasNextInt()){
sectInfo.add(tempScan.nextInt());
} else {
temp = tempScan.next();
if(temp.equals(""))
break;
char c = temp.charAt(0);
sectInfo.add(c);
}
if(i == 4){
sysMan.createSection(sysMan.getLastAddedAirline(), sysMan.getLastAddedFlightID(), (char)sectInfo.get(0), (int)sectInfo.get(1), (char)sectInfo.get(2), (int)sectInfo.get(3));
i = 1;
sectInfo = null;
sectInfo = new ArrayList();
continue;
}
i++;
}
}while(!temp.equals("\\s+"));
}while(!temp.contains("\\s+"));
}catch(NullPointerException e){
System.err.println(e);
}
}
I'd rather chunk it down by regexp mathing the outer bounds, have a look, I took it a couple of levels broken.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Tokeni {
static String yolo = "[DEN,NYC,SEA,LAX]{AMER["
+ "AA1|2018,10,8,16,30|DEN|LAX[E:200:S:4,F:500:S:2],"
+ "AA2|2018,8,9,7,30|LAX|DEN[E:200:S:5,F:500:S:3]],"
+ "UNTD[UA21|2018,11,8,12,30|NYC|SEA[E:300:S:6,F:800:S:3],"
+ "UA12|2018,8,9,7,30|SEA|DEN[B:700:S:5, F:1200:S:2]]}";
public static void main(String[] args) {
Matcher airportCodesMatcher = Pattern.compile("\\[(.*?)\\]").matcher(yolo);
airportCodesMatcher.find();
String[] airportCodes = airportCodesMatcher.group(1).split(",");
Matcher airLinesMatcher = Pattern.compile("\\{(.*?)\\}").matcher(yolo);
airLinesMatcher.find();
String airLinesStr = airLinesMatcher.group(1);
System.out.println(airLinesStr);
Pattern airLinePattern = Pattern.compile("\\D+\\[(.*?)\\]\\]");
Matcher airLineMatcher = airLinePattern.matcher(airLinesStr);
while( airLineMatcher.find() ) {
String airLineStr = airLineMatcher.group(0).trim();
if(airLineStr.startsWith(",")) {
airLineStr = airLineStr.substring(1, airLineStr.length()).trim();
}
System.out.println(airLineStr);
Matcher airLineNameMatcher = Pattern.compile("[A-Z]+").matcher(airLineStr);
airLineNameMatcher.find();
String airLineName = airLineNameMatcher.group(0).trim();
System.out.println(airLineName);
airLineStr = airLineStr.substring(airLineStr.indexOf("[")+1, airLineStr.length());
Matcher airLineInfoMatcher = Pattern.compile("\\D+(.*?)\\]").matcher(airLineStr);
while(airLineInfoMatcher.find()) {
String airLineInfoStr = airLineInfoMatcher.group(0).trim();
if(airLineInfoStr.startsWith(",")) {
airLineInfoStr = airLineInfoStr.substring(1, airLineInfoStr.length()).trim();
}
System.out.println(airLineInfoStr);
}
}
}
}
I need to add some or clauses to query. I need to do it in a loop.
StringTokenizer st = new StringTokenizer(symptoms, ",");
while(st.hasMoreTokens()){
qb.whereOr(Properties.Symptom.like("%" + st.nextToken() + "%"));
}
How I can add those or conditions properly, because this above is not working as expected. I want to add or for every symptom.
If you look at the documentation, you'll see that whereOr() takes an unbounded number of conditions. What you want to do is add them all at once in an array:
StringTokenizer st = new StringTokenizer(symptoms, ",");
ArrayList<WhereCondition> whereConditions = new ArrayList<WhereCondition>();
while(st.hasMoreTokens()){
whereConditions.add(Properties.Symptom.like("%" + st.nextToken() + "%"));
}
// Give the ArrayList an already allocated array to place its contents in.
WhereCondition[] conditionsArray = new WhereCondition[whereConditions.size()];
conditionsArray = whereConditions.toArray(conditionsArray);
qb.whereOr(conditionsArray);
It looks like the method call in the documentation takes two non-array WhereConditions and then an ellipsized argument, which accepts an array or an additional comma-separated list of objects. So you might have to do something like this to get it to work properly:
qb.whereOr(conditionsArray[0], conditionsArray[1], Arrays.copyOfRange(conditionsArray, 2, conditionsArray.length));
ADDENDUM: It looks like you're using APIs that don't match the documentation, possibly an older version of greenDAO. I wrote this solution based off the current documentation. I can't guarantee that it will work for you. I recommend updating if possible.
Try this:
StringTokenizer st = new StringTokenizer(symptoms, ",");
WhereCondition where = null;
while(st.hasMoreTokens()){
if (where != null) {
where = qb.or(where, Properties.Symptom.like("%" + st.nextToken() + "%"));
} else {
where = Properties.Symptom.like("%" + st.nextToken() + "%");
}
}
qb.where(where).list();
I had the same problem so I added my own method in an Util class to perform the same behavior when I have one or several WhereCondition in an array.
Here is my gateway method :
public static QueryBuilder whereOr(QueryBuilder queryBuilder, WhereCondition[] whereConditions){
if(whereConditions == null) return queryBuilder.where(null);
else if(whereConditions.length == 1) return queryBuilder.where(whereConditions[0]);
else return queryBuilder.whereOr(whereConditions[0], whereConditions[1], Arrays.copyOfRange(whereConditions, 2, whereConditions.length));
}
Use : Util.whereOr(queryBuilder, whereConditionsArray);
Default : Can't use the Builder Pattern from the QueryBuilder with this approach
(More later) Here, I share you some code which could spare you time when developping DAO methods.
public class QueryBuilderUtil {
public static final String EQ = "=?";
public static final String NOTEQ = "<>?";
public static final String LIKE = " LIKE ?";
public static final String GE = ">=?";
public static final String LE = "<=?";
public static final String GT = ">?";
public static final String LT = "<?";
public static QueryBuilder whereOrOnSamePropertyWithDifferentValues(QueryBuilder queryBuilder, Property property, String operation, String values, String separator) {
return whereOrOnSamePropertyWithDifferentValues(queryBuilder, property, operation, values.split(separator));
}
public static QueryBuilder whereOrOnSamePropertyWithDifferentValues(QueryBuilder queryBuilder, Property property, String operation, String[] values) {
WhereCondition[] whereConditions = new WhereCondition[values.length];
int i = 0;
for (String value : values) {
whereConditions[i++] = new WhereCondition.PropertyCondition(property, operation, value);
}
return whereOr(queryBuilder, whereConditions);
}
public static QueryBuilder whereOr(QueryBuilder queryBuilder, WhereCondition[] whereConditions) {
if (whereConditions == null) return queryBuilder.where(null);
else if (whereConditions.length == 1) return queryBuilder.where(whereConditions[0]);
else return queryBuilder.whereOr(whereConditions[0], whereConditions[1], Arrays.copyOfRange(whereConditions, 2, whereConditions.length));
}
}
With this class, you can perform a whereOr with the same property on multiples "values string" in one line. It was necessary to clean my code :). However you can only do simple operations like variables declared in the class.
Example :
public List<Block> loadAllByModId(String mods_id) {
synchronized (this) {
QueryBuilder<Block> queryBuilder = queryBuilder();
QueryBuilderUtil.whereOrOnSamePropertyWithDifferentValues(queryBuilder, Properties.ModId, QueryBuilderUtil.EQ, mods_id, ";");
query_list = queryBuilder.build();
}
Query<Block> query = query_list.forCurrentThread();
return query.list();
}
Hope it helps
I'm trying to create a validate java class that receives 4 inputs from an object passed as 1 from the requester. The class needs to convert float inputs to string and evaluate each input to meet a certain format and then throw exceptions complete with error message and code when it fails.
What I have is in two methods and would like to know if there is a better way to combine these two classes into one validate method for the main class to call. I don't seem to be able to get around using the pattern/matcher concept to insure the inputs are formatted correctly. Any help you can give would be very much appreciated.
public class Validator {
private static final String MoneyPattern ="^\\d{1,7}(\\.\\d{1,2})$" ;
private static final String PercentagePattern = "^\\d{1,3}\\.\\d{1,2}$";
private static final String CalendarYearPattern = "^20[1-9][0-9]$";
private int errorcode = 0;
private String errormessage = null;
public Validator(MyInput input){
}
private boolean verifyInput(){
String Percentage = ((Float) input.getPercentage().toString();
String Income = ((Float) input.getIncome().toString();
String PublicPlan = ((Float) input.getPublicPlan().toString();
String Year = ((Float) input.getYear();
try {
if (!doesMatch(Income, MoneyPattern)) {
errormessage = errormessage + "income,";
}
if (!doesMatch(PublicPlan, MoneyPattern)) {
errormessage = errormessage + "insurance plan,";
}
if (!doesMatch(Percentage, PercentagePattern)) {
errormessage = errormessage + "Percentage Plan,";
}
if (!doesMatch(Year, CalendarYearPattern)) {
errormessage = errormessage + "Year,";
}
} catch (Exception e){
errorcode = 111;
errormessage = e.getMessage();
}
}
private boolean doesMatch(String s, String pattern) throws Exception{
try {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(s);
if (!s.equals("")){
if(m.find()){
return true;
} else {
return false;
}
}else {
return false;
}
} catch (PatternSyntaxException pse){
errorcode = 111;
errormessage = pse.getMessage();
}
}
}
This code is borked from the word "go". You have a constructor into which you pass a MyInput reference, but there's no code in the ctor and no private data member to receive it. It looks like you expect to use input in your doesMatch() method, but it's a NullPointerException waiting to happen.
Your code doesn't follow the Sun Java coding standards; variable names should be lower case.
Why you wouldn't do that input validation in the ctor, when you actually receive the value, is beyond me. Perhaps you really meant to pass it into that verifyInput() method.
I would worry about correctness and readability before concerning myself with efficiency.
I'd have methods like this:
public boolean isValidMoney(String money) { // put the regex here }
public boolean isValidYear(String year) { // the regex here }
I think I'd prefer a real Money class to a String. There's no abstraction whatsoever.
Here's one bit of honesty:
private static final String CalendarYearPattern = "^20[1-9][0-9]$";
I guess you either don't think this code will still be running in the 22nd century or you won't be here to maintain it.
One way of doing this would be with DynamicBeans.
package com.acme.validator;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.beanutils.PropertyUtils;
public class Validator {
//A simple optimisation of the pattern
private static final Pattern MoneyPattern = Pattern.compile("^\\d{1,7}(\\.\\d{1,2})$");
private static final Pattern PercentagePattern = Pattern.compile("^\\d{1,3}\\.\\d{1,2}$");
private static final Pattern CalendarYearPattern = Pattern.compile("^20[1-9][0-9]$");
public String Validator(MyInput input) {
String errormessage = "";
/*
* Setting these up as Maps.
* Ideally this would be a 'simple bean'
* but that goes beyond the scope of the
* original question
*/
Map<String,Pattern> patternMap = new HashMap<String,Pattern>();
patternMap.put("percentage", PercentagePattern);
patternMap.put("publicPlan", MoneyPattern);
patternMap.put("income", MoneyPattern);
patternMap.put("year", CalendarYearPattern);
Map<String,String> errorMap = new HashMap<String,String>();
errorMap.put("percentage", "Percentage Plan,");
errorMap.put("publicPlan", "insurance plan,");
errorMap.put("income", "income,");
errorMap.put("year", "Year,");
for (String key : patternMap.keySet()) {
try {
String match = ((Float) PropertyUtils.getSimpleProperty(input, key)).toString();
Matcher m = patternMap.get(key).matcher(match);
if ("".equals(match) || !m.find()) {
errormessage = errormessage + errorMap.get(key);
}
} catch (Exception e) {
errormessage = e.getMessage(); //since getMessage() could be null, you need to work out some way of handling this in the response
//don't know the point of the error code so remove this altogether
break; //Assume an exception trumps any validation failure
}
}
return errormessage;
}
}
I've made a few assumptions about the validation rules (for simplicity used 2 maps but you could also use a single map and a bean containing both the Pattern and the Message and even the 'error code' if that is important).
The key 'flaw' in your original setup and what would hamper the solution above, is that you are using 'year' as Float in the input bean.
(new Float(2012)).toString()
The above returns "2012.0". This will always fail your pattern. When you start messing about with the different types of objects potentially in the input bean, you may need to consider ensuring they are String at the time of creating the input bean and not, as is the case here, when they are retrieved.
Good Luck with the rest of your Java experience.