private void checkInfo(WordnetRuleInfo info) throws LexicalResourceException {
   if (info == null) throw new LexicalResourceException("got null info");
   if ((info.getLeftSenseNo() != -1 && info.getLeftSenseNo() < 1)
       || (info.getRightSenseNo() != -1 && info.getRightSenseNo() < 1))
     throw new LexicalResourceException(
         "one of the sense ordinal in the input WordnetRuleInfo is not valid, got "
             + info.getLeftSenseNo()
             + " for left and for right "
             + info.getRightSenseNo());
 }
  /**
   * Return all the rules matching the given lemma+pos on one side of the rule, filtered to the
   * given relations and info.
   *
   * @param lemma
   * @param pos
   * @param relations
   * @param info
   * @param chainingLength
   * @param isFromRight
   * @return
   * @throws LexicalResourceException
   */
  List<LexicalRule<? extends WordnetRuleInfo>> getRulesForSide(
      String lemma,
      PartOfSpeech pos,
      Set<WordNetRelation> relations,
      WordnetRuleInfo info,
      int chainingLength,
      boolean isFromRight)
      throws LexicalResourceException {
    // sanity
    checkRelationsBeforeUse(relations);
    checkInfo(info);

    List<LexicalRule<? extends WordnetRuleInfo>> rulesList =
        new ArrayList<
            LexicalRule<? extends WordnetRuleInfo>>(); // use Set to eliminate duplicate rules

    int sourceSenseNum, targetSenseNum;
    if (isFromRight) {
      sourceSenseNum = info.getRightSenseNo();
      targetSenseNum = info.getLeftSenseNo();
    } else {
      sourceSenseNum = info.getLeftSenseNo();
      targetSenseNum = info.getRightSenseNo();
    }
    // carefully pull the synset
    List<Synset> synsets = pullSynsets(lemma, pos, sourceSenseNum);

    try {
      for (int synsetNo = 1; synsetNo <= synsets.size(); synsetNo++) {
        Synset synset = synsets.get(synsetNo - 1);
        for (WordNetRelation relation : relations) {
          if (relation.equals(SYNONYM))
            rulesList.addAll(getSynonymRules(synset, synsetNo, lemma, isFromRight, targetSenseNum));
          else {
            // when querying words on the right, look to the left, using the symmetric relation
            WordNetRelation relationToQuery =
                isFromRight ? relation.getSymmetricRelation() : relation;

            try {
              if (relationToQuery != null) // 	getSymmetricRelation() may return null
              for (SensedWord neighborSensedWord :
                    getSemanticOrLexicalNeighborSensedWords(
                        lemma, synset, relationToQuery, chainingLength)) {
                  // construct a rule from all this data we now have
                  Synset neighborSynset = neighborSensedWord.getSynset();
                  PartOfSpeech originPos;
                  PartOfSpeech neighborPos;
                  try {
                    originPos = synset.getPartOfSpeech().toPartOfSpeech();
                    neighborPos = neighborSynset.getPartOfSpeech().toPartOfSpeech();
                  } catch (WordNetException e) {
                    throw new LexicalResourceException(
                        "Bug! this POS from wordnet '"
                            + neighborSynset.getPartOfSpeech()
                            + "' isn't valid");
                  }
                  String neighborLemma = neighborSensedWord.getWord();

                  boolean addThisRule = true;
                  if (targetSenseNum != -1) {
                    addThisRule =
                        isCorrectSenseOfGivenWord(
                            neighborSynset,
                            neighborLemma,
                            neighborSynset.getPartOfSpeech(),
                            targetSenseNum);
                  }

                  if (addThisRule) {
                    LexicalRule<WordnetRuleInfo> rule =
                        newDirectedRule(
                            neighborLemma,
                            neighborPos,
                            lemma,
                            originPos,
                            relation,
                            neighborSynset,
                            synset,
                            synsetNo,
                            isFromRight);
                    if (!rulesList.contains(rule)) rulesList.add(rule);
                  }
                }
            } catch (WordNetException e) {
              throw new LexicalResourceException("wordnet error occured, see nested", e);
            }
          }
        }
      }
    } catch (LexicalResourceException e) {
      throw new LexicalResourceException(
          "An error occured while extracting the neighbors for <" + lemma + ", " + pos + ">", e);
    }

    return rulesList;
  }
  /**
   * Return all the rules matching the given lemma+pos of both sides of the rule, filtered to the
   * given relations and info. The rules are between 1 and #chainingLength WN edges long.
   *
   * @param lLemma
   * @param lPos
   * @param rLemma
   * @param rPos
   * @param relations
   * @param info
   * @param chainingLength
   * @return
   * @throws LexicalResourceException
   */
  List<LexicalRule<? extends WordnetRuleInfo>> getRules(
      String lLemma,
      PartOfSpeech lPos,
      String rLemma,
      PartOfSpeech rPos,
      Set<WordNetRelation> relations,
      WordnetRuleInfo info,
      int chainingLength)
      throws LexicalResourceException {
    // sanity
    checkRelationsBeforeUse(relations);
    checkInfo(info);
    if (lLemma == null) throw new LexicalResourceException("got null lLemma");
    if (rLemma == null) throw new LexicalResourceException("got null rLemma");

    List<LexicalRule<? extends WordnetRuleInfo>> rules =
        new Vector<LexicalRule<? extends WordnetRuleInfo>>();
    // carefully pull the two synsets
    List<Synset> lSelectSynsets = pullSynsets(lLemma, lPos, info.getLeftSenseNo());
    List<Synset> rSelectSynsets = pullSynsets(rLemma, rPos, info.getRightSenseNo());

    try {
      for (int lSynsetNo = 1; lSynsetNo <= lSelectSynsets.size(); lSynsetNo++) {
        Synset lSynset = lSelectSynsets.get(lSynsetNo - 1);

        for (int rSynsetNo = 1; rSynsetNo <= rSelectSynsets.size(); rSynsetNo++) {
          Synset rSynset = rSelectSynsets.get(rSynsetNo - 1);

          for (WordNetRelation relation : relations) {
            Set<Synset> neighbors =
                getSemanticOrLexicalNeighbors(lLemma, lSynset, relation, chainingLength);
            if (neighbors.contains(rSynset)
                || // usually, the relation connects between neighboring synsets
                doubleCheckContains(neighbors, rSynset)
                || (relation.equals(SYNONYM)
                    && lSynset.equals(
                        rSynset))) // special condition for SYNONYMs, which are just words within a
                                   // Synset
            {
              // just in case the given rPos or lPos are null, replace them with the POSs from the
              // synsets
              PartOfSpeech concreteLPos = lSynset.getPartOfSpeech().toPartOfSpeech();
              PartOfSpeech concreteRPos = rSynset.getPartOfSpeech().toPartOfSpeech();
              rules.add(
                  new LexicalRule<WordnetRuleInfo>(
                      lLemma,
                      concreteLPos,
                      rLemma,
                      concreteRPos,
                      relation.toString(),
                      RESOURCE_NAME,
                      new WordnetRuleInfo(lSynset, lSynsetNo, rSynset, rSynsetNo, relation)));
            }
          }
        }
      }
    } catch (WordNetException e) {
      throw new LexicalResourceException(
          "An error occured while loading the neighbors of a synset of <"
              + lLemma
              + ", "
              + lPos
              + "> :",
          e);
    }

    return rules;
  }