/**
  * @param RedBeanModel $precedingModel
  * @param null|string $precedingRelation
  * @return array
  * @throws NotSupportedException if there the preceding model and relation are not either both defined or both
  * null
  */
 protected function getDerivedRelationsViaCastedUpModelData(RedBeanModel $precedingModel = null, $precedingRelation = null)
 {
     if ($precedingModel != null && $precedingRelation == null || $precedingModel == null && $precedingRelation != null) {
         throw new NotSupportedException();
     }
     $attributes = array();
     $metadata = $this->model->getMetadata();
     foreach ($metadata as $modelClassName => $modelClassMetadata) {
         if (isset($metadata[$modelClassName]["derivedRelationsViaCastedUpModel"])) {
             foreach ($metadata[$modelClassName]["derivedRelationsViaCastedUpModel"] as $relation => $derivedRelationData) {
                 $modelClassName = get_class($this->model);
                 if (!$this->derivedRelationLinksToPrecedingRelation($modelClassName::getDerivedRelationModelClassName($relation), $modelClassName::getDerivedRelationViaCastedUpModelOpposingRelationName($relation), $precedingModel, $precedingRelation)) {
                     $attributes[$relation] = array('label' => $this->model->getAttributeLabel($relation));
                 }
             }
         }
     }
     return $attributes;
 }
 /**
  * Process derived relations assignment
  * @param RedBeanModel $primaryModel
  * @param RedBeanModel $selectedModel
  */
 protected static function processDerivedRelationsAssignment($primaryModel, $selectedModel)
 {
     assert('$primaryModel instanceof RedBeanModel');
     assert('$selectedModel instanceof RedBeanModel');
     $metadata = $selectedModel->getMetadata();
     foreach ($metadata as $modelClassName => $modelClassMetadata) {
         if (isset($metadata[$modelClassName]["derivedRelationsViaCastedUpModel"])) {
             foreach ($metadata[$modelClassName]["derivedRelationsViaCastedUpModel"] as $relation => $derivedRelationData) {
                 $opposingModelClassName = $derivedRelationData[1];
                 $opposingRelation = $derivedRelationData[2];
                 if ($opposingRelation == 'activityItems' && is_subclass_of($opposingModelClassName, 'Activity')) {
                     $opposingModels = $opposingModelClassName::getByActivityItemsCastedDown($selectedModel->getClassId('Item'));
                     if ($opposingModels != null) {
                         foreach ($opposingModels as $opposingModel) {
                             $opposingModel->activityItems->add($primaryModel);
                             $opposingModel->save();
                         }
                     }
                 }
             }
         }
     }
 }