diff --git a/src/cli/java/org/commcare/util/screen/EntityScreenContext.java b/src/cli/java/org/commcare/util/screen/EntityScreenContext.java index c6b50b99e8..4a8f5735d7 100644 --- a/src/cli/java/org/commcare/util/screen/EntityScreenContext.java +++ b/src/cli/java/org/commcare/util/screen/EntityScreenContext.java @@ -3,7 +3,7 @@ /** * Holds essential meta data associated with the entity screen */ -public class EntityScreenContext { +public class EntityScreenContext extends ScreenContext{ private final int mOffSet; private final String mSearchText; private final int mSortIndex; @@ -21,6 +21,7 @@ public class EntityScreenContext { public EntityScreenContext(int offset, String searchText, int sortIndex, int casesPerPage, String[] selectedValues, String detailSelection, boolean isFuzzySearch) { + super(true); mOffSet = offset; mSearchText = searchText; mSortIndex = sortIndex; @@ -31,6 +32,11 @@ public EntityScreenContext(int offset, String searchText, int sortIndex, int cas } public EntityScreenContext() { + this(true); + } + + public EntityScreenContext(boolean respectRelevancy) { + super(respectRelevancy); mOffSet = 0; mSearchText = null; mSortIndex = 0; diff --git a/src/cli/java/org/commcare/util/screen/MenuScreen.java b/src/cli/java/org/commcare/util/screen/MenuScreen.java index 9ac439cf48..c43115d5aa 100644 --- a/src/cli/java/org/commcare/util/screen/MenuScreen.java +++ b/src/cli/java/org/commcare/util/screen/MenuScreen.java @@ -59,6 +59,20 @@ public boolean handleAutoMenuAdvance(SessionWrapper sessionWrapper, boolean resp return false; } + /** + * Checks whether a menu with given menuId exists and is a visible option on menu screen + * @param menuId id of the menu we want to check visiblility for + * @return true if menu exists and is visible, false otherwise + */ + public boolean isMenuVisible(String menuId) { + for (MenuDisplayable menuDisplayable : getMenuDisplayables()) { + if(menuDisplayable.getCommandID().contentEquals(menuId)){ + return true; + } + } + return false; + } + class ScreenLogger implements LoggerInterface { @Override diff --git a/src/cli/java/org/commcare/util/screen/ScreenContext.java b/src/cli/java/org/commcare/util/screen/ScreenContext.java new file mode 100644 index 0000000000..0a1c3b2ea3 --- /dev/null +++ b/src/cli/java/org/commcare/util/screen/ScreenContext.java @@ -0,0 +1,13 @@ +package org.commcare.util.screen; +public class ScreenContext { + + private boolean respectRelevancy; + + public ScreenContext(boolean respectRelevancy) { + this.respectRelevancy = respectRelevancy; + } + + public boolean isRespectRelevancy() { + return respectRelevancy; + } +} diff --git a/src/main/java/org/commcare/core/interfaces/HttpResponseProcessor.java b/src/main/java/org/commcare/core/interfaces/HttpResponseProcessor.java index a922464635..c4e027accd 100644 --- a/src/main/java/org/commcare/core/interfaces/HttpResponseProcessor.java +++ b/src/main/java/org/commcare/core/interfaces/HttpResponseProcessor.java @@ -12,7 +12,7 @@ public interface HttpResponseProcessor { /** * Http response was in the 200s */ - void processSuccess(int responseCode, InputStream responseData); + void processSuccess(int responseCode, InputStream responseData, String apiVersion); /** * Http response was in the 400s. diff --git a/src/main/java/org/commcare/core/interfaces/ResponseStreamAccessor.java b/src/main/java/org/commcare/core/interfaces/ResponseStreamAccessor.java index 2309b441f0..d628e62f83 100644 --- a/src/main/java/org/commcare/core/interfaces/ResponseStreamAccessor.java +++ b/src/main/java/org/commcare/core/interfaces/ResponseStreamAccessor.java @@ -5,4 +5,5 @@ public interface ResponseStreamAccessor { InputStream getResponseStream() throws IOException; + String getApiVersion(); } diff --git a/src/main/java/org/commcare/core/network/ModernHttpRequester.java b/src/main/java/org/commcare/core/network/ModernHttpRequester.java index 3429596d00..6ea3104e7f 100644 --- a/src/main/java/org/commcare/core/network/ModernHttpRequester.java +++ b/src/main/java/org/commcare/core/network/ModernHttpRequester.java @@ -33,7 +33,7 @@ * * @author Phillip Mates (pmates@dimagi.com) */ -public class ModernHttpRequester implements ResponseStreamAccessor { +public class ModernHttpRequester { /** * How long to wait when opening network connection in milliseconds */ @@ -87,7 +87,23 @@ public void makeRequestAndProcess() { } try { response = makeRequest(); - processResponse(responseProcessor, response.code(), this); + final ModernHttpRequester requester = this; + processResponse(responseProcessor, response.code(), new ResponseStreamAccessor() { + /** + * Only gets called if response processor is supplied + * @return Input Stream from cache + * @throws IOException if an io error happens while reading or writing to cache + */ + @Override + public InputStream getResponseStream() throws IOException { + return requester.getResponseStream(response); + } + + @Override + public String getApiVersion() { + return requester.getApiVersion(); + } + }); } catch (IOException e) { e.printStackTrace(); responseProcessor.handleIOException(e); @@ -153,7 +169,8 @@ public static void processResponse(HttpResponseProcessor responseProcessor, responseProcessor.handleIOException(e); return; } - responseProcessor.processSuccess(responseCode, responseStream); + String apiVersion = streamAccessor.getApiVersion(); + responseProcessor.processSuccess(responseCode, responseStream, apiVersion); } finally { StreamsUtil.closeStream(responseStream); } @@ -181,14 +198,8 @@ public InputStream getResponseStream(Response response) throws IOE return cache.retrieveCache(); } - /** - * Only gets called if response processor is supplied - * @return Input Stream from cache - * @throws IOException if an io error happens while reading or writing to cache - */ - @Override - public InputStream getResponseStream() throws IOException { - return getResponseStream(response); + public String getApiVersion() { + return response != null ? response.headers().get("x-api-current-version") : null; } public static RequestBody getPostBody(Multimap inputs) { diff --git a/src/main/java/org/javarosa/core/model/FormDef.java b/src/main/java/org/javarosa/core/model/FormDef.java index 0b93a05c19..30b86e31b2 100755 --- a/src/main/java/org/javarosa/core/model/FormDef.java +++ b/src/main/java/org/javarosa/core/model/FormDef.java @@ -55,7 +55,6 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.NoSuchElementException; import java.util.Vector; @@ -1855,4 +1854,13 @@ public String dispatchSendCallout(String url, Multimap paramMap) return sendCalloutHandler.performHttpCalloutForResponse(url, paramMap); } } + + // Checks if the form element at given form Index belongs to a non counted repeat + public boolean isNonCountedRepeat(FormIndex formIndex) { + IFormElement currentElement = getChild(formIndex); + if (currentElement instanceof GroupDef && ((GroupDef)currentElement).isRepeat()) { + return ((GroupDef)currentElement).getCountReference() == null; + } + return false; + } } diff --git a/src/main/java/org/javarosa/form/api/FormEntryCaption.java b/src/main/java/org/javarosa/form/api/FormEntryCaption.java index 9beb6ec7d5..8fdb23d4fb 100644 --- a/src/main/java/org/javarosa/form/api/FormEntryCaption.java +++ b/src/main/java/org/javarosa/form/api/FormEntryCaption.java @@ -1,9 +1,11 @@ package org.javarosa.form.api; +import org.commcare.cases.util.StringUtils; import org.javarosa.core.model.FormDef; import org.javarosa.core.model.FormIndex; import org.javarosa.core.model.GroupDef; import org.javarosa.core.model.IFormElement; +import org.javarosa.core.services.locale.Localization; import org.javarosa.core.services.locale.Localizer; import java.util.Hashtable; @@ -217,35 +219,37 @@ public String getRepeatText(String typeKey) { String caption = null; if ("mainheader".equals(typeKey)) { - caption = g.mainHeader; + caption = getCaptionText(g.mainHeader); if (caption == null) { return title; } } else if ("add".equals(typeKey)) { - caption = g.addCaption; + caption = getCaptionText(g.addCaption); if (caption == null) { - return "Add another " + title; + return Localization.getWithDefault("repeat.dialog.add.another", new String[]{title}, + "Add another " + title); } } else if ("add-empty".equals(typeKey)) { - caption = g.addEmptyCaption; + caption = getCaptionText(g.addEmptyCaption); if (caption == null) { - caption = g.addCaption; + caption = getCaptionText(g.addCaption); } if (caption == null) { - return "None - Add " + title; + return Localization.getWithDefault("repeat.dialog.add.new", new String[]{title}, + "Add a new " + title); } } else if ("del".equals(typeKey)) { - caption = g.delCaption; + caption = getCaptionText(g.delCaption); if (caption == null) { return "Delete " + title; } } else if ("done".equals(typeKey)) { - caption = g.doneCaption; + caption = getCaptionText(g.doneCaption); if (caption == null) { return "Done"; } } else if ("done-empty".equals(typeKey)) { - caption = g.doneEmptyCaption; + caption = getCaptionText(g.doneEmptyCaption); if (caption == null) { caption = g.doneCaption; } @@ -253,7 +257,7 @@ public String getRepeatText(String typeKey) { return "Skip"; } } else if ("delheader".equals(typeKey)) { - caption = g.delHeader; + caption = getCaptionText(g.delHeader); if (caption == null) { return "Delete which " + title + "?"; } @@ -265,6 +269,16 @@ public String getRepeatText(String typeKey) { return form.fillTemplateString(caption, index.getReference(), vars); } + private String getCaptionText(String textIdOrText) { + if (!StringUtils.isEmpty(textIdOrText)) { + String returnText = getIText(textIdOrText, null); + if (returnText != null) { + return substituteStringArgs(returnText); + } + } + return substituteStringArgs(textIdOrText); + } + //this should probably be somewhere better public int getNumRepetitions() { return form.getNumRepetitions(index); @@ -284,11 +298,11 @@ private String getRepetitionText(String type, FormIndex index, boolean newrep) { String caption = null; if ("header".equals(type)) { - caption = g.entryHeader; + caption = getCaptionText(g.entryHeader); } else if ("choose".equals(type)) { - caption = g.chooseCaption; + caption = getCaptionText(g.chooseCaption); if (caption == null) { - caption = g.entryHeader; + caption = getCaptionText(g.entryHeader); } } if (caption == null) { diff --git a/src/main/java/org/javarosa/form/api/FormEntryModel.java b/src/main/java/org/javarosa/form/api/FormEntryModel.java index 757d4b7c36..4fc153eb8c 100644 --- a/src/main/java/org/javarosa/form/api/FormEntryModel.java +++ b/src/main/java/org/javarosa/form/api/FormEntryModel.java @@ -625,4 +625,8 @@ public String getDebugInfo(FormIndex index, String category) { return TraceSerialization.serializeEvaluationTrace(indexDebug.get(category), TraceSerialization.TraceInfoType.FULL_PROFILE, false); } + + public boolean isNonCountedRepeat() { + return getForm().isNonCountedRepeat(getFormIndex()); + } } diff --git a/src/main/java/org/javarosa/xform/parse/XFormParser.java b/src/main/java/org/javarosa/xform/parse/XFormParser.java index c8b5a3bdbb..a94098838c 100755 --- a/src/main/java/org/javarosa/xform/parse/XFormParser.java +++ b/src/main/java/org/javarosa/xform/parse/XFormParser.java @@ -1,5 +1,6 @@ package org.javarosa.xform.parse; +import org.commcare.cases.util.StringUtils; import org.javarosa.core.model.Constants; import org.javarosa.core.model.DataBinding; import org.javarosa.core.model.FormDef; @@ -1082,27 +1083,38 @@ private void parseGroupLabel(GroupDef g, Element e) { Vector usedAtts = new Vector<>(); usedAtts.addElement(REF_ATTR); + String labelItextId = getItextReference(e); + g.setTextID(labelItextId); + if (labelItextId == null) { + String label = getLabel(e); + g.setLabelInnerText(label); + } - String label = getLabel(e); - String ref = e.getAttributeValue("", REF_ATTR); + if (XFormUtils.showUnusedAttributeWarning(e, usedAtts)) { + reporter.warning(XFormParserReporter.TYPE_UNKNOWN_MARKUP, XFormUtils.unusedAttWarning(e, usedAtts), getVagueLocation(e)); + } + } + private String getItextReference(Element e) { + String ref = e.getAttributeValue("", REF_ATTR); if (ref != null) { if (ref.startsWith(ITEXT_OPEN) && ref.endsWith(ITEXT_CLOSE)) { String textRef = ref.substring(ITEXT_OPEN.length(), ref.indexOf(ITEXT_CLOSE)); - verifyTextMappings(textRef, "Group