diff --git a/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java b/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java index c8a957643..e1864ad2d 100644 --- a/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java +++ b/src/main/java/org/commcare/formplayer/services/MenuSessionFactory.java @@ -24,6 +24,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.List; +import java.util.Optional; import java.util.Vector; /** @@ -62,14 +63,17 @@ public class MenuSessionFactory { */ @Trace public void rebuildSessionFromFrame(MenuSession menuSession, CaseSearchHelper caseSearchHelper) throws CommCareSessionException, RemoteInstanceFetcher.RemoteInstanceException { - Vector steps = menuSession.getSessionWrapper().getFrame().getSteps(); + List steps = menuSession.getSessionWrapper().getFrame().getSteps().stream().filter( + step -> !step.getType().equals(SessionFrame.STATE_MARK) + ).toList(); menuSession.resetSession(); EntityScreenContext entityScreenContext = new EntityScreenContext(); Screen screen = menuSession.getNextScreen(false, entityScreenContext); int processedStepsCount = 0; boolean needsFullInit = false; - while (screen != null) { - String currentStep = null; + while (screen != null && processedStepsCount < steps.size()) { + String input = null; + StackFrameStep currentStep = steps.get(processedStepsCount); if (screen instanceof MenuScreen) { if (menuSession.autoAdvanceMenu(screen, storageFactory.getPropertyManager().isAutoAdvanceMenu())) { screen = menuSession.getNextScreen(needsFullInit, entityScreenContext); @@ -78,12 +82,10 @@ public void rebuildSessionFromFrame(MenuSession menuSession, CaseSearchHelper ca MenuDisplayable[] options = ((MenuScreen)screen).getMenuDisplayables(); for (int i = 0; i < options.length; i++) { - for (StackFrameStep step : steps) { - if (step.getId().equals(options[i].getCommandID())) { - currentStep = String.valueOf(i); - // final step, needs to init fully to show to screen - needsFullInit = ++processedStepsCount == steps.size(); - } + if (currentStep.getId().equals(options[i].getCommandID())) { + input = String.valueOf(i); + // final step, needs to init fully to show to screen + needsFullInit = ++processedStepsCount == steps.size(); } } } else if (screen instanceof EntityScreen) { @@ -92,28 +94,27 @@ public void rebuildSessionFromFrame(MenuSession menuSession, CaseSearchHelper ca SessionDatum neededDatum = entityScreen.getSession().getNeededDatum(); Vector actions = entityScreen.getShortDetail().getCustomActions(entityScreen.getEvalContext()); outer: - for (StackFrameStep step : steps) { - if (step.getType().equals(SessionFrame.STATE_DATUM_VAL) && step.getId().equals(neededDatum.getDataId())) { - if (entityScreen.referencesContainStep(step.getValue())) { - currentStep = step.getValue(); - needsFullInit = ++processedStepsCount == steps.size(); - } - break; - } else if (step.getType().equals(SessionFrame.STATE_COMMAND_ID) && !actions.isEmpty()) { - for (int i = 0; i < actions.size(); i++) { - Action action = actions.get(i); - if (action.getStackOperations() != null) { - for (StackOperation operation : action.getStackOperations()) { - List commandSteps = operation.getStackFrameSteps().stream() - .filter(s -> s.getType().equals(SessionFrame.STATE_COMMAND_ID)).toList(); - for (StackFrameStep s : commandSteps) { - String value = s.evaluateValue(entityScreen.getEvalContext()); - if (value.equals(step.getId())) { - currentStep = "action " + i; - needsFullInit = ++processedStepsCount == steps.size(); - break outer; - } - } + if (currentStep.getType().equals(SessionFrame.STATE_DATUM_VAL) && currentStep.getId().equals(neededDatum.getDataId())) { + if (entityScreen.referencesContainStep(currentStep.getValue())) { + input = currentStep.getValue(); + needsFullInit = ++processedStepsCount == steps.size(); + } + } else if (currentStep.getType().equals(SessionFrame.STATE_COMMAND_ID) && !actions.isEmpty()) { + // this is messy and gross, but we need to find the action that corresponds to this step + for (int i = 0; i < actions.size(); i++) { + Action action = actions.get(i); + if (action.getStackOperations() != null) { + for (StackOperation operation : action.getStackOperations()) { + Optional commandStep = operation.getStackFrameSteps().stream() + .filter(s -> s.getType().equals(SessionFrame.STATE_COMMAND_ID)).findFirst(); + if (commandStep.isEmpty()) { + continue; + } + String value = commandStep.get().evaluateValue(entityScreen.getEvalContext()); + if (value.equals(currentStep.getId())) { + input = "action " + i; + needsFullInit = ++processedStepsCount == steps.size(); + break outer; } } } @@ -121,55 +122,53 @@ public void rebuildSessionFromFrame(MenuSession menuSession, CaseSearchHelper ca } // Only init subscreen if we are not going to auto-launch a different screen - String nextInput = currentStep == null ? "" : currentStep; + String nextInput = input == null ? "" : input; entityScreen.evaluateAutoLaunch(nextInput); if (entityScreen.getAutoLaunchAction() == null) { entityScreen.initListSubScreen(); } - if (currentStep != null && currentStep != NEXT_SCREEN && entityScreen.shouldBeSkipped()) { - menuSession.handleInput(currentStep, needsFullInit, true, false, entityScreenContext); + if (input != null && input != NEXT_SCREEN && entityScreen.shouldBeSkipped()) { + menuSession.handleInput(input, needsFullInit, true, false, entityScreenContext); screen = menuSession.getNextScreen(needsFullInit, entityScreenContext); continue; } } else if (screen instanceof QueryScreen) { QueryScreen queryScreen = (QueryScreen)screen; RemoteQueryDatum neededDatum = (RemoteQueryDatum) menuSession.getSessionWrapper().getNeededDatum(); - for (StackFrameStep step : steps) { - if (step.getId().equals(neededDatum.getDataId())) { - URI uri = null; - try { - uri = new URI(step.getValue()); - } catch (URISyntaxException e) { - e.printStackTrace(); - throw new CommCareSessionException("Query URL format error: " + e.getMessage(), e); - } - ImmutableMultimap.Builder dataBuilder = ImmutableMultimap.builder(); - step.getExtras().forEach((key, value) -> dataBuilder.put(key, (String) value)); - try { - ExternalDataInstance searchDataInstance = caseSearchHelper.getRemoteDataInstance( - queryScreen.getQueryDatum().getDataId(), - queryScreen.getQueryDatum().useCaseTemplate(), - uri.toURL(), - dataBuilder.build(), - false - ); - queryScreen.updateSession(searchDataInstance, dataBuilder.build()); - screen = menuSession.getNextScreen(needsFullInit, entityScreenContext); - currentStep = NEXT_SCREEN; - break; - } catch (InvalidStructureException | IOException | XmlPullParserException | UnfullfilledRequirementsException e) { - e.printStackTrace(); - throw new CommCareSessionException("Query response format error: " + e.getMessage(), e); - } + if (currentStep.getId().equals(neededDatum.getDataId())) { + URI uri = null; + try { + uri = new URI(currentStep.getValue()); + } catch (URISyntaxException e) { + e.printStackTrace(); + throw new CommCareSessionException("Query URL format error: " + e.getMessage(), e); + } + ImmutableMultimap.Builder dataBuilder = ImmutableMultimap.builder(); + currentStep.getExtras().forEach((key, value) -> dataBuilder.put(key, (String) value)); + try { + ExternalDataInstance searchDataInstance = caseSearchHelper.getRemoteDataInstance( + queryScreen.getQueryDatum().getDataId(), + queryScreen.getQueryDatum().useCaseTemplate(), + uri.toURL(), + dataBuilder.build(), + false + ); + queryScreen.updateSession(searchDataInstance, dataBuilder.build()); + needsFullInit = ++processedStepsCount == steps.size(); + screen = menuSession.getNextScreen(needsFullInit, entityScreenContext); + input = NEXT_SCREEN; + } catch (InvalidStructureException | IOException | XmlPullParserException | UnfullfilledRequirementsException e) { + e.printStackTrace(); + throw new CommCareSessionException("Query response format error: " + e.getMessage(), e); } } } - if (currentStep == null) { + if (input == null) { break; - } else if (currentStep != NEXT_SCREEN) { - menuSession.handleInput(currentStep, needsFullInit, true, false, entityScreenContext); - menuSession.addSelection(currentStep); + } else if (input != NEXT_SCREEN) { + menuSession.handleInput(input, needsFullInit, true, false, entityScreenContext); + menuSession.addSelection(input); screen = menuSession.getNextScreen(needsFullInit, entityScreenContext); } }