/// <summary>
        /// Determines the default dependency value for a fragmentflow. not fast.
        /// </summary>
        /// <param name="repository"></param>
        /// <param name="fragmentFlowId"></param>
        /// <param name="scenarioId"></param>
        /// <returns></returns>
        public static double? GetDefaultValue(this IRepository<FragmentFlow> repository,
            int fragmentFlowId, int scenarioId = Scenario.MODEL_BASE_CASE_ID)
        {
            FragmentFlow fragmentFlow = repository.Queryable()
                .Where(k => k.FragmentFlowID == fragmentFlowId)
                .Where(k => k.ParentFragmentFlow.NodeTypeID == 1)
                .FirstOrDefault();
            if (fragmentFlow == null)
                return null;

            var ncm = new NodeCacheModel()
            {
                NodeTypeID = 1,
                FragmentFlowID = (int)fragmentFlow.ParentFragmentFlowID
            };

            var parentNode = repository.LTerminate(ncm, scenarioId, false);

            return repository.GetRepository<ProcessFlow>().FlowExchange((int)parentNode.ProcessID, fragmentFlow.FlowID,
                comp(fragmentFlow.DirectionID)); // double comp!
        }
        /// <summary>
        /// Determine dependency flows required by the fragmentflow termination being supplied.
        /// This function assumes that all flow+direction combinations are distinct for processes and fragments.
        /// (for fragments, node outflows are grouped by flow+direction)
        /// </summary>
        /// <param name="term">FragmentNodeResource corresponding to the terminus of the current FragmentFlow</param>
        /// <param name="ex_directionId">Direction of the physical flow with respect to the *parent*</param>
        /// <param name="flow_exch">out param set equal to the inflow's exchange</param>
        /// <returns></returns>
        public IEnumerable<InventoryModel> GetScenarioProductFlows(NodeCacheModel theFragmentFlow, int scenarioId, out double nodeWeight, out int? ilcdEntityId)
        {
            FlowTerminationModel term = _fragmentFlowService.Terminate(theFragmentFlow,scenarioId, true); // resolve background

            // first, calculate node weight
            double? flow_conv = _flowFlowPropertyService.FlowConv(theFragmentFlow.FlowID, term.TermFlowID, scenarioId);
            if (flow_conv == null)
            {
                throw new ArgumentNullException("Flow conversion was not found and cannot be null");
            }

            double flow_exch;
            // and incoming exchange
            // note this is not subject to parameter adjustment
            IEnumerable<InventoryModel> Outflows;

            switch (term.NodeTypeID)
            {
                case 1:
                    {
                        // process-- lookup exchange and outflows separately
                        //var _flow_exch = _processFlowService.FlowExchange((int)term.ProcessID, term.TermFlowID, theFragmentFlow.DirectionID);
                        //if (_flow_exch == null)
                        //{
                        //    throw new ArgumentNullException("Process inflow not found!");
                        //}
                        //flow_exch = (double)_flow_exch;

                        //Outflows = _processFlowService.GetDependencies((int)term.ProcessID, term.TermFlowID, theFragmentFlow.DirectionID);

                        if (term.BalanceFFID == null)
                        {
                            // no conservation performed
                            var FFM = _processFlowService.LookupDependencies(theFragmentFlow.FragmentFlowID, term, scenarioId).ToList();
                            flow_exch = (double)FFM.Where(k => k.FlowID == term.TermFlowID && k.DirectionID != theFragmentFlow.DirectionID)
                                .Select(k => k.Result).First();
                            Outflows = FFM.Where(k => k.FragmentFlowID != null).ToList();
                        }
                        else
                        {
                            var CM = _processFlowService.LookupConservationFlows(theFragmentFlow.FragmentFlowID, term, scenarioId).ToList();
                            flow_exch = (double)CM.Where(k => k.FlowID == term.TermFlowID && k.DirectionID != theFragmentFlow.DirectionID)
                                .Select(k => k.Result).First();

                            var balanceDir = CM.Where(k => k.FragmentFlowID == term.BalanceFFID).Select(k => k.DirectionID).First();

                            var balance = CM.Where(k => k.DirectionID != balanceDir).Sum(k => k.FlowPropertyResult)
                                        - CM.Where(k => k.DirectionID == balanceDir).Where(k => k.FragmentFlowID != term.BalanceFFID)
                                        .Sum(k => k.FlowPropertyResult);

                            foreach (var bf in CM.Where(k => k.FragmentFlowID == term.BalanceFFID))
                                bf.FlowPropertyResult = balance;

                            Outflows = CM.Where(k => k.FragmentFlowID != null).ToList();

                        }

                        break;
                    }
                case 2:
                    {
                        // does the subfragment exist in the cache? if so, use that
                        if (_nodeCacheService.IsCached((int)term.SubFragmentID,term.ScenarioID))
                            Outflows = _fragmentFlowService.GetDependencies((int)term.SubFragmentID, term.TermFlowID, theFragmentFlow.DirectionID,
                                out flow_exch, term.ScenarioID);
                        else
                        {
                            // have we already traversed this subfragment in this unit of work?
                            int subFragRefFlow = _fragmentFlowService
                                .Query(k => k.FragmentID == term.SubFragmentID && k.ParentFragmentFlowID == null)
                                .Select(k => k.FragmentFlowID).First();
                            if (!nodeCaches.Any(k => k.FragmentFlowID == subFragRefFlow))
                            {
                                // if not, we need to
                                Traverse((int)term.SubFragmentID, term.ScenarioID);
                            }
                            // access the cache to determine outflow amounts
                            //Outflows = _fragmentFlowService.GetDependencies((int)term.SubFragmentID,term.TermFlowID,ex_directionId,
                            //    out flow_exch, term.ScenarioID);
                            Outflows = GetDependencies((int)term.SubFragmentID, term.TermFlowID, theFragmentFlow.DirectionID,
                                out flow_exch, term.ScenarioID);
                        }
                        break;
                    }
                default:
                    {
                        Outflows = new List<InventoryModel>();
                        flow_exch = 1;
                        break;
                    }
            }
            if (flow_exch == 0)
            {
                throw new ArgumentException("The inflow result cannot be 0");
            }

            nodeWeight = (double)flow_conv / flow_exch;
            ilcdEntityId = term.ILCDEntityID;

            return Outflows;
        }
        /// <summary>
        /// Lazy flow termination-- FNF and FNP are looked up now
        /// </summary>
        /// <param name="repository"></param>
        /// <param name="ff"></param>
        /// <param name="scenarioId"></param>
        /// <param name="doBackground"></param>
        /// <returns></returns>
        public static FlowTerminationModel LTerminate(this IRepository<FragmentFlow> repository, 
						     NodeCacheModel ff, int scenarioId, bool doBackground)
        {
            var fragmentNode = new FlowTerminationModel();
            int inFlowId;
            switch (ff.NodeTypeID)
            {
                case 1:
                    {
                        fragmentNode = repository.LGetFragmentNodeProcess(ff.FragmentFlowID, scenarioId);
                        break;
                    }
                case 2:
                    {
                        fragmentNode = repository.LGetFragmentNodeFragment(ff.FragmentFlowID, scenarioId);
                        break;
                    }
                case 3:
                {
                    if (ff.FlowID == null)
                    {
                        throw new ArgumentNullException("FragmentFlow.FlowID must be set!");
                    }
                    fragmentNode.NodeTypeID = 3;
                    //fragmentNode.ILCDEntityID = ff.FragmentFlowID;
                    fragmentNode.ScenarioID = scenarioId;
                    fragmentNode.TermFlowID = (int)ff.FlowID;
                    break;
                }
                default:
                {
                    if (ff.FlowID == null)
                    {
                        throw new ArgumentNullException("FragmentFlow.FlowID must be set!");
                    }
                    else inFlowId = (int)ff.FlowID;
                    if (doBackground)
                    {
                        fragmentNode = repository.GetRepository<Background>()
                            .ResolveBackground(inFlowId, ff.DirectionID, scenarioId);
                    }
                    else
                    {
                        //fragmentNode.ILCDEntityID = ff.FragmentFlowID;
                        fragmentNode.ScenarioID = scenarioId;
                        fragmentNode.TermFlowID = inFlowId;
                    }
                    break;
                }
              	        }
            return fragmentNode;
        }