hari7775 commited on
Commit
dc0fcda
Β·
1 Parent(s): a4e1ec4

Fix experience section parsing

Browse files
src/main/java/com/resumeparser/processor/EntityExtractor.java CHANGED
@@ -310,10 +310,10 @@ public class EntityExtractor {
310
  "CERTIFICATIONS", "LANGUAGES", "SUMMARY", "ACHIEVEMENTS"
311
  );
312
 
313
- Pattern datePattern = Pattern.compile("(\\b\\d{4}\\b|\\b[A-Z][a-z]{2,8}\\s+\\d{4}\\b)(\\s*[-—–]\\s*(\\b\\d{4}\\b|\\b[A-Z][a-z]{2,8}\\s+\\d{4}\\b|Present))?");
314
 
315
  // Split by double newline
316
- String[] parts = text.split("\\n\\n+");
317
  for (String part : parts) {
318
  String trimmed = part.trim();
319
  if (trimmed.isEmpty()) continue;
@@ -333,24 +333,109 @@ public class EntityExtractor {
333
  }
334
  if (isBlacklisted) continue;
335
 
336
- // Simple heuristic to split title/dates/description
337
- // Input: Title + Dates (Line 1), Company + Location (Line 2), Description (Lines 3+)
338
- String titleAndDates = firstLine;
339
- String companyInfo = lines.length > 1 ? lines[1].trim() : "";
340
- StringBuilder descBuilder = new StringBuilder();
341
- for (int i = 2; i < lines.length; i++) {
342
- descBuilder.append(lines[i].trim()).append("\n");
 
 
 
 
 
 
 
 
343
  }
344
 
345
- String title = titleAndDates;
346
- String dates = "";
347
- Matcher m = datePattern.matcher(titleAndDates);
348
- if (m.find()) {
349
- dates = m.group().trim();
350
- title = titleAndDates.replace(dates, "").trim().replaceAll("\\s*[-—–]\\s*$", "").trim();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  }
352
 
353
- experience.add(new Candidate.Experience(companyInfo, title, dates, descBuilder.toString().trim()));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  }
355
  return experience;
356
  }
 
310
  "CERTIFICATIONS", "LANGUAGES", "SUMMARY", "ACHIEVEMENTS"
311
  );
312
 
313
+ Pattern datePattern = Pattern.compile("(?i)(\\b[A-Za-z]{3,9}\\.?\\s+\\d{4}|\\b\\d{4})\\s*(?:[-—–]|to)\\s*(\\b[A-Za-z]{3,9}\\.?\\s+\\d{4}|\\b\\d{4}|Present)");
314
 
315
  // Split by double newline
316
+ String[] parts = text.split("\\n\\s*\\n+");
317
  for (String part : parts) {
318
  String trimmed = part.trim();
319
  if (trimmed.isEmpty()) continue;
 
333
  }
334
  if (isBlacklisted) continue;
335
 
336
+ // Pre-process: join lines that are split mid-sentence or mid-date
337
+ List<String> cleanLines = new ArrayList<>();
338
+ for (int i = 0; i < lines.length; i++) {
339
+ String current = lines[i].trim();
340
+ if (current.isEmpty()) continue;
341
+
342
+ boolean endsWithMonth = current.matches(".*\\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\\.?$");
343
+ boolean endsWithDash = current.endsWith("-") || current.endsWith("–") || current.endsWith("β€”") || current.toLowerCase().endsWith("to");
344
+
345
+ if ((endsWithMonth || endsWithDash) && i + 1 < lines.length) {
346
+ String next = lines[i + 1].trim();
347
+ current = current + " " + next;
348
+ i++;
349
+ }
350
+ cleanLines.add(current);
351
  }
352
 
353
+ if (cleanLines.isEmpty()) continue;
354
+
355
+ String titleLine = cleanLines.get(0);
356
+ String companyInfo = cleanLines.size() > 1 ? cleanLines.get(1) : "";
357
+
358
+ String startDate = "";
359
+ String endDate = "";
360
+ String datesStr = "";
361
+
362
+ // Find dates in titleLine or companyInfo or any of the lines
363
+ boolean dateFound = false;
364
+ for (int i = 0; i < cleanLines.size(); i++) {
365
+ String line = cleanLines.get(i);
366
+ Matcher dateMatcher = datePattern.matcher(line);
367
+ if (dateMatcher.find()) {
368
+ datesStr = dateMatcher.group(0).trim();
369
+ startDate = dateMatcher.group(1).trim();
370
+ endDate = dateMatcher.group(2).trim();
371
+
372
+ cleanLines.set(i, line.replace(dateMatcher.group(0), "").trim());
373
+ dateFound = true;
374
+ break;
375
+ }
376
+ }
377
+
378
+ titleLine = cleanLines.get(0).replaceAll("(?i)^\\s*(?:Link|Present|Date|Dates|Timeline|Timeline:)?\\s*[|:\\-–—]+\\s*", "")
379
+ .replaceAll("(?i)\\s*[|:\\-–—]+\\s*(?:Link|Present|Date|Dates|Timeline|Timeline:)?\\s*$", "")
380
+ .trim();
381
+
382
+ if (cleanLines.size() > 1) {
383
+ companyInfo = cleanLines.get(1).replaceAll("(?i)^\\s*(?:Link|Present|Date|Dates|Timeline|Timeline:)?\\s*[|:\\-–—]+\\s*", "")
384
+ .replaceAll("(?i)\\s*[|:\\-–—]+\\s*(?:Link|Present|Date|Dates|Timeline|Timeline:)?\\s*$", "")
385
+ .trim();
386
  }
387
 
388
+ int descStartIndex = 2;
389
+ if (titleLine.isEmpty() && cleanLines.size() > 1) {
390
+ titleLine = companyInfo;
391
+ companyInfo = cleanLines.size() > 2 ? cleanLines.get(2) : "";
392
+ descStartIndex = 3;
393
+ }
394
+
395
+ // Extract location from companyInfo
396
+ String companyName = companyInfo;
397
+ String location = "";
398
+ if (companyInfo.contains(",")) {
399
+ int commaIdx = companyInfo.lastIndexOf(",");
400
+ String beforeComma = companyInfo.substring(0, commaIdx).trim();
401
+ String afterComma = companyInfo.substring(commaIdx + 1).trim();
402
+
403
+ int lastSpace = beforeComma.lastIndexOf(" ");
404
+ if (lastSpace >= 0) {
405
+ location = beforeComma.substring(lastSpace + 1).trim() + ", " + afterComma;
406
+ companyName = beforeComma.substring(0, lastSpace).trim();
407
+ } else {
408
+ location = beforeComma + ", " + afterComma;
409
+ companyName = "";
410
+ }
411
+ }
412
+
413
+ // Extract description & bullets
414
+ List<String> bulletsList = new ArrayList<>();
415
+ StringBuilder descBuilder = new StringBuilder();
416
+
417
+ for (int i = descStartIndex; i < cleanLines.size(); i++) {
418
+ String line = cleanLines.get(i).trim();
419
+ if (line.isEmpty()) continue;
420
+
421
+ if (line.contains("mailto:") || line.startsWith("http") || line.contains("github.com") || line.contains("linkedin.com")) {
422
+ continue; // skip noise lines at the end
423
+ }
424
+
425
+ descBuilder.append(line).append("\n");
426
+ String cleanBullet = line.replaceAll("^[\\sβ€’\\-*β–ͺ]+", "").trim();
427
+ if (!cleanBullet.isEmpty()) {
428
+ bulletsList.add(cleanBullet);
429
+ }
430
+ }
431
+
432
+ Candidate.Experience exp = new Candidate.Experience(companyName, titleLine, datesStr, descBuilder.toString().trim());
433
+ exp.setFromDate(startDate);
434
+ exp.setToDate(endDate);
435
+ exp.setLocation(location);
436
+ exp.setBullets(bulletsList);
437
+
438
+ experience.add(exp);
439
  }
440
  return experience;
441
  }