protected org.kuali.rice.krad.bo.DataObjectRelationship getRelationshipMetadata(
      Class<?> dataObjectClass, String attributeName, String attributePrefix) {

    RelationshipDefinition relationshipDefinition =
        getDictionaryRelationship(dataObjectClass, attributeName);
    if (relationshipDefinition == null) {
      return null;
    }

    org.kuali.rice.krad.bo.DataObjectRelationship dataObjectRelationship =
        new org.kuali.rice.krad.bo.DataObjectRelationship(
            relationshipDefinition.getSourceClass(),
            relationshipDefinition.getObjectAttributeName(),
            relationshipDefinition.getTargetClass());

    if (!StringUtils.isEmpty(attributePrefix)) {
      attributePrefix += ".";
    }

    List<PrimitiveAttributeDefinition> primitives = relationshipDefinition.getPrimitiveAttributes();
    for (PrimitiveAttributeDefinition primitiveAttributeDefinition : primitives) {
      dataObjectRelationship
          .getParentToChildReferences()
          .put(
              attributePrefix + primitiveAttributeDefinition.getSourceName(),
              primitiveAttributeDefinition.getTargetName());
    }

    return dataObjectRelationship;
  }
  public List<String> getRelationshipNames(String entryName) {
    DataDictionaryEntryBase entry =
        (DataDictionaryEntryBase) getDataDictionary().getDictionaryObjectEntry(entryName);

    List<String> relationshipNames = new ArrayList<String>();
    for (RelationshipDefinition def : entry.getRelationships()) {
      relationshipNames.add(def.getObjectAttributeName());
    }
    return relationshipNames;
  }
  public Class<? extends BusinessObject> getRelationshipTargetClass(
      String entryName, String relationshipName) {
    Class targetClass = null;

    RelationshipDefinition rd = getRelationshipDefinition(entryName, relationshipName);
    if (rd != null) {
      targetClass = rd.getTargetClass();
    }

    return targetClass;
  }
  public Class<? extends BusinessObject> getRelationshipSourceClass(
      String entryName, String relationshipName) {
    Class sourceClass = null;

    RelationshipDefinition rd = getRelationshipDefinition(entryName, relationshipName);
    if (rd != null) {
      sourceClass = rd.getSourceClass();
    }

    return sourceClass;
  }
 /**
  * @see
  *     org.kuali.rice.krad.service.DataDictionaryService#getRelationshipAttributeMap(java.lang.String,
  *     java.lang.String)
  */
 public Map<String, String> getRelationshipAttributeMap(
     String entryName, String relationshipName) {
   Map<String, String> attributeMap = new HashMap<String, String>();
   RelationshipDefinition relationshipDefinition =
       getRelationshipDefinition(entryName, relationshipName);
   for (Iterator iter = relationshipDefinition.getPrimitiveAttributes().iterator();
       iter.hasNext(); ) {
     PrimitiveAttributeDefinition attribute = (PrimitiveAttributeDefinition) iter.next();
     attributeMap.put(attribute.getTargetName(), attribute.getSourceName());
   }
   return attributeMap;
 }
  public List<String> getRelationshipTargetAttributes(String entryName, String relationshipName) {
    List<String> targetAttributes = null;

    RelationshipDefinition rd = getRelationshipDefinition(entryName, relationshipName);
    if (rd != null) {
      targetAttributes = new ArrayList<String>();

      for (PrimitiveAttributeDefinition pad : rd.getPrimitiveAttributes()) {
        targetAttributes.add(pad.getTargetName());
      }
    }

    return targetAttributes;
  }
  public List<String> getRelationshipEntriesForTargetAttribute(
      String entryName, String targetAttributeName) {
    List<String> relationships = new ArrayList<String>();

    DataDictionaryEntryBase entry =
        (DataDictionaryEntryBase) getDataDictionary().getDictionaryObjectEntry(entryName);

    for (RelationshipDefinition def : entry.getRelationships()) {
      for (PrimitiveAttributeDefinition pddef : def.getPrimitiveAttributes()) {
        if (StringUtils.equals(targetAttributeName, pddef.getTargetName())) {
          relationships.add(def.getObjectAttributeName());
          break;
        }
      }
    }
    return relationships;
  }
  protected org.kuali.rice.krad.bo.DataObjectRelationship
      populateRelationshipFromDictionaryReference(
          Class<?> dataObjectClass,
          RelationshipDefinition ddReference,
          String attributePrefix,
          boolean keysOnly) {
    org.kuali.rice.krad.bo.DataObjectRelationship relationship =
        new org.kuali.rice.krad.bo.DataObjectRelationship(
            dataObjectClass, ddReference.getObjectAttributeName(), ddReference.getTargetClass());

    for (PrimitiveAttributeDefinition def : ddReference.getPrimitiveAttributes()) {
      if (StringUtils.isNotBlank(attributePrefix)) {
        relationship
            .getParentToChildReferences()
            .put(attributePrefix + "." + def.getSourceName(), def.getTargetName());
      } else {
        relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
      }
    }

    if (!keysOnly) {
      for (SupportAttributeDefinition def : ddReference.getSupportAttributes()) {
        if (StringUtils.isNotBlank(attributePrefix)) {
          relationship
              .getParentToChildReferences()
              .put(attributePrefix + "." + def.getSourceName(), def.getTargetName());
          if (def.isIdentifier()) {
            relationship.setUserVisibleIdentifierKey(attributePrefix + "." + def.getSourceName());
          }
        } else {
          relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
          if (def.isIdentifier()) {
            relationship.setUserVisibleIdentifierKey(def.getSourceName());
          }
        }
      }
    }

    return relationship;
  }
  /**
   * This method does validation on the quickfinderParameterString and
   * quickfinderParameterStringBuilderClass members
   *
   * @param rootBusinessObjectClass
   * @param boMetadataService
   */
  private void validateQuickfinderParameters(
      Class rootBusinessObjectClass, BusinessObjectMetaDataService boMetadataService) {
    if (quickfinderParameterStringBuilderClass != null && quickfinderParameterString != null) {
      throw new AttributeValidationException(
          "Both quickfinderParameterString and quickfinderParameterStringBuilderClass can not be specified on attribute "
              + getAttributeName()
              + " in rootBusinessObjectClass "
              + rootBusinessObjectClass.getName());
    }

    // String used for building exception messages
    String quickfinderParameterStringSource = "quickfinderParameterString";

    if (quickfinderParameterStringBuilderClass != null) {
      try {
        quickfinderParameterStringSource =
            "quickfinderParameterStringBuilderClass "
                + quickfinderParameterStringBuilderClass.getCanonicalName();
        quickfinderParameterString =
            quickfinderParameterStringBuilderClass.newInstance().getValue();
      } catch (InstantiationException e) {
        throw new ClassValidationException(
            "unable to create new instance of "
                + quickfinderParameterStringSource
                + " while validating rootBusinessObjectClass '"
                + rootBusinessObjectClass.getName()
                + "'",
            e);
      } catch (IllegalAccessException e) {
        throw new ClassValidationException(
            "unable to create new instance of "
                + quickfinderParameterStringSource
                + " while validating rootBusinessObjectClass '"
                + rootBusinessObjectClass.getName()
                + "'",
            e);
      }
    }

    if (!StringUtils.isEmpty(quickfinderParameterString)) {
      // quickfinderParameterString will look something like "campusTypeCode=P,active=Y"
      for (String quickfinderParam :
          quickfinderParameterString.split(",")) { // this is guaranteed to return at least one
        if (quickfinderParam.contains("=")) {
          String propertyName = quickfinderParam.split("=")[0];
          RelationshipDefinition relationship =
              boMetadataService.getBusinessObjectRelationshipDefinition(
                  rootBusinessObjectClass, attributeName);
          Class targetClass = relationship.getTargetClass();

          // This is insufficient to ensure the property is valid for a lookup default, but it's
          // better than nothing.
          if (!DataDictionary.isPropertyOf(targetClass, propertyName)) {
            throw new ClassValidationException(
                "malformed parameter string  '"
                    + quickfinderParameterString
                    + "' from "
                    + quickfinderParameterStringSource
                    + ", '"
                    + propertyName
                    + "' is not a property of "
                    + targetClass
                    + "' for rootBusinessObjectClass '"
                    + rootBusinessObjectClass.getName()
                    + "'");
          }

        } else {
          throw new ClassValidationException(
              "malformed parameter string '"
                  + quickfinderParameterString
                  + "' from "
                  + quickfinderParameterStringSource
                  + " for rootBusinessObjectClass '"
                  + rootBusinessObjectClass.getName()
                  + "'");
        }
      }
    }
  }
  /**
   * gets the relationship that the attribute represents on the class
   *
   * @param c - the class to which the attribute belongs
   * @param attributeName - property name for the attribute
   * @return a relationship definition for the attribute
   */
  @Override
  public RelationshipDefinition getDictionaryRelationship(Class<?> c, String attributeName) {
    DataDictionaryEntry entryBase =
        KRADServiceLocatorWeb.getDataDictionaryService()
            .getDataDictionary()
            .getDictionaryObjectEntry(c.getName());
    if (entryBase == null) {
      return null;
    }

    RelationshipDefinition relationship = null;

    List<RelationshipDefinition> ddRelationships = entryBase.getRelationships();

    int minKeys = Integer.MAX_VALUE;
    for (RelationshipDefinition def : ddRelationships) {
      // favor key sizes of 1 first
      if (def.getPrimitiveAttributes().size() == 1) {
        for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
          if (primitive.getSourceName().equals(attributeName)
              || def.getObjectAttributeName().equals(attributeName)) {
            relationship = def;
            minKeys = 1;
            break;
          }
        }
      } else if (def.getPrimitiveAttributes().size() < minKeys) {
        for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
          if (primitive.getSourceName().equals(attributeName)
              || def.getObjectAttributeName().equals(attributeName)) {
            relationship = def;
            minKeys = def.getPrimitiveAttributes().size();
            break;
          }
        }
      }
    }

    // check the support attributes
    if (relationship == null) {
      for (RelationshipDefinition def : ddRelationships) {
        if (def.hasIdentifier()) {
          if (def.getIdentifier().getSourceName().equals(attributeName)) {
            relationship = def;
          }
        }
      }
    }

    return relationship;
  }