protected static <T> void parseEDISegmentOrSegmentGroup(
      EDIMessage ediMessage,
      T object,
      Iterator<Field> fieldIterator,
      Queue<String> lookAhead,
      SegmentIterator segmentIterator)
      throws EDIMessageException, IllegalAccessException, InvocationTargetException,
          InstantiationException, ClassNotFoundException, ConversionException {
    if (!fieldIterator.hasNext()) {
      throw new EDIMessageException("No more fields to read.");
    }

    if (!segmentIterator.hasNext() && lookAhead.size() == 0) {
      return;
    }

    // get the queued object first...
    String line = lookAhead.size() > 0 ? lookAhead.remove() : segmentIterator.next();

    // match up the field with the line...
    FieldMatch fm = advanceToMatch(ediMessage, fieldIterator, line);

    //

    if (fm != null) {
      Class<?> fieldType = getEDISegmentOrGroupType(fm.getField());
      if (fieldType.isAnnotationPresent(EDISegment.class)) {
        processSegment(ediMessage, object, lookAhead, segmentIterator, fm);
      } else if (fieldType.isAnnotationPresent(EDISegmentGroup.class)) {
        processSegmentGroup(ediMessage, object, lookAhead, segmentIterator, fm);
      }
    } else {
      lookAhead.add(line);
    }
  }
 public boolean isValid(final Object value, final ConstraintValidatorContext context) {
   boolean isValid = false;
   BeanWrapper beanWrapper = new BeanWrapperImpl(value);
   final Object field = beanWrapper.getPropertyValue(constraint.field());
   final Object match = beanWrapper.getPropertyValue(constraint.match());
   isValid = field == match || field != null && field.equals(match);
   if (!isValid) {
     context
         .buildConstraintViolationWithTemplate(constraint.message())
         .addNode(constraint.match())
         .addConstraintViolation();
   }
   return isValid;
 }
  protected static <T> void processSegment(
      EDIMessage ediMessage,
      T object,
      Queue<String> lookAhead,
      SegmentIterator SegmentIterator,
      FieldMatch fm)
      throws InstantiationException, IllegalAccessException, InvocationTargetException,
          ClassNotFoundException, ConversionException {

    if (Collection.class.isAssignableFrom(fm.getField().getType())) {
      Collection obj = CollectionFactory.newInstance(fm.getField().getType());
      BeanUtils.setProperty(object, fm.getField().getName(), obj);

      // look ahead to see if we need to break.
      Class<?> collectionClass = getCollectionType(fm.getField());

      if (collectionClass.isAnnotationPresent(EDISegment.class)) {
        EDISegment es = collectionClass.getAnnotation(EDISegment.class);

        // first, go ahead and add the object from the field match.
        Object matchObject = collectionClass.newInstance();

        parseEDISegmentFields(ediMessage, matchObject, fm.getLine());
        obj.add(matchObject);

        Queue<String> segments = queueLinesForType(ediMessage, es, lookAhead, SegmentIterator);
        for (String segment : segments) {
          Object collectionObject = collectionClass.newInstance();
          parseEDISegmentFields(ediMessage, collectionObject, segment);
          obj.add(collectionObject);
        }
      }
    } else {
      Object obj = fm.getField().getType().newInstance();
      BeanUtils.setProperty(object, fm.getField().getName(), obj);
      parseEDISegmentFields(ediMessage, obj, fm.getLine());
    }
  }
  protected static <T> void processSegmentGroup(
      EDIMessage ediMessage,
      T object,
      Queue<String> lookAhead,
      SegmentIterator segmentIterator,
      FieldMatch fm)
      throws InstantiationException, IllegalAccessException, InvocationTargetException,
          ClassNotFoundException, ConversionException, EDIMessageException {

    LOG.debug("Object: " + ReflectionToStringBuilder.toString(object));
    LOG.debug("Field: " + fm.getField().getName());

    Class<?> segmentGroupClass = getEDISegmentOrGroupType(fm.getField());
    if (!segmentGroupClass.isAnnotationPresent(EDISegmentGroup.class)) {
      throw new EDIMessageException("Segment Group should have annotation.");
    }

    LOG.debug("Segment Group Type: " + segmentGroupClass);

    String line = fm.getLine();
    EDISegmentGroup es = segmentGroupClass.getAnnotation(EDISegmentGroup.class);

    if (StringUtils.equals(es.header(), line)) {
      // feed line.
    } else {
      LOG.debug("Adding to Look Ahead: " + line);
      lookAhead.add(line);
    }

    if (Collection.class.isAssignableFrom(fm.getField().getType())) {
      Collection obj = CollectionFactory.newInstance(fm.getField().getType());
      BeanUtils.setProperty(object, fm.getField().getName(), obj);

      String segmentTag = getSegmentTag(fm.getField(), true);

      while (true) {
        LOG.debug("Looping to collect Collection of Segment Groups");
        // parse the group...
        Field[] fields = segmentGroupClass.getDeclaredFields();
        final List<Field> fieldsList = Arrays.asList(fields);
        ListIterator<Field> fieldIterator = fieldsList.listIterator(0);

        Object collectionObj = segmentGroupClass.newInstance();
        while (fieldIterator.hasNext() && (segmentIterator.hasNext() || lookAhead.size() > 0)) {
          if (startOfNewRecursiveObject(fieldIterator, fieldsList, segmentGroupClass)) {
            String next = lookAhead.size() > 0 ? lookAhead.remove() : segmentIterator.next();
            lookAhead.add(next);
            if (!isSegmentHeirarchicalLevelAndDeeperLevel(
                line, next, Character.toString(ediMessage.elementDelimiter()))) {
              LOG.debug("Reaching new instance of list.");
              break;
            }
          }
          parseEDISegmentOrSegmentGroup(
              ediMessage, collectionObj, fieldIterator, lookAhead, segmentIterator);
        }

        obj.add(collectionObj);

        // look to next line...
        String nextLine = lookAhead.size() > 0 ? lookAhead.remove() : segmentIterator.next();
        // get the first element of the line.
        StrTokenizer nextLineTokenizer = new StrTokenizer(nextLine, ediMessage.elementDelimiter());

        if (StringUtils.equals(segmentTag, nextLineTokenizer.nextToken())) {
          if (!isSegmentEqual(line, nextLine, Character.toString(ediMessage.elementDelimiter()))) {
            LOG.debug("Reaching new collection");
            lookAhead.add(nextLine);
            break;
          }
          LOG.debug("Might be a repeat..");
          LOG.debug("Next line: " + line);
          lookAhead.add(nextLine);
        } else {
          lookAhead.add(nextLine);
          break;
        }

        // now, look ahead to see whether the next line is of the same
        // object type..
        if (!segmentIterator.hasNext() && lookAhead.size() == 0) {
          break;
        }
      }

    } else {
      Field[] fields = segmentGroupClass.getDeclaredFields();
      Iterator<Field> fieldIterator = Arrays.asList(fields).iterator();

      Object obj = segmentGroupClass.newInstance();
      while (fieldIterator.hasNext() && (segmentIterator.hasNext() || lookAhead.size() > 0)) {
        parseEDISegmentOrSegmentGroup(ediMessage, obj, fieldIterator, lookAhead, segmentIterator);
      }

      BeanUtils.setProperty(object, fm.getField().getName(), obj);
    }

    // look at next...
    if (StringUtils.isNotBlank(es.header())) {
      line = lookAhead.size() > 0 ? lookAhead.remove() : segmentIterator.next();

      if (StringUtils.endsWith(es.footer(), line)) {
        // feed line.
        LOG.debug("Popping footer off of the line iterator.");
      } else {
        lookAhead.add(line);
      }
    }
  }
 @Override
 public void initialize(final FieldMatch constraintAnnotation) {
   firstFieldName = constraintAnnotation.first();
   secondFieldName = constraintAnnotation.second();
   type = constraintAnnotation.type();
 }