From 975b45da364dadfe8d86c2b0e71eebba980e7511 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 21 Mar 2024 20:12:42 +1100 Subject: [PATCH] more work on translations --- .../fhir/r5/elementmodel/LanguageUtils.java | 121 +++++++++++++++++- .../java/org/hl7/fhir/r5/model/DataType.java | 47 ++++--- .../org/hl7/fhir/r5/model/MarkdownType.java | 5 + .../org/hl7/fhir/r5/model/StringType.java | 13 +- 4 files changed, 154 insertions(+), 32 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java index 6bdee88d7..a454ad9da 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/LanguageUtils.java @@ -9,12 +9,19 @@ import java.util.Set; import org.checkerframework.checker.units.qual.cd; import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent; import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent; +import org.hl7.fhir.r5.model.ContactDetail; import org.hl7.fhir.r5.model.DataType; +import org.hl7.fhir.r5.model.ElementDefinition; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent; import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; @@ -142,7 +149,12 @@ public class LanguageUtils { public int importFromTranslations(Element resource, List translations, List messages) { Set usedUnits = new HashSet<>(); - int r = importFromTranslations(null, resource, translations, usedUnits); + int r = 0; + if (resource.fhirType().equals("StructureDefinition")) { + r = importFromTranslationsForSD(null, resource, translations, usedUnits); + } else { + r = importFromTranslations(null, resource, translations, usedUnits); + } for (TranslationUnit t : translations) { if (!usedUnits.contains(t)) { messages.add(new ValidationMessage(Source.Publisher, IssueType.INFORMATIONAL, t.getId(), "Unused '"+t.getLanguage()+"' translation '"+t.getSrcText()+"' -> '"+t.getTgtText()+"'", IssueSeverity.INFORMATION)); @@ -152,6 +164,62 @@ public class LanguageUtils { } + /* + * */ + private int importFromTranslationsForSD(Object object, Element resource, List translations, Set usedUnits) { + int r = 0; + r = r + checkForTranslations(translations, usedUnits, resource, "name", "name"); + r = r + checkForTranslations(translations, usedUnits, resource, "title", "title"); + r = r + checkForTranslations(translations, usedUnits, resource, "publisher", "publisher"); + for (Element cd : resource.getChildrenByName("contact")) { + r = r + checkForTranslations(translations, usedUnits, cd, "contact.name", "name"); + } + r = r + checkForTranslations(translations, usedUnits, resource, "purpose", "purpose"); + r = r + checkForTranslations(translations, usedUnits, resource, "copyright", "copyright"); + Element diff = resource.getNamedChild("differential"); + if (diff != null) { + for (Element ed : diff.getChildrenByName("element")) { + String id = ed.getNamedChildValue("id"); + r = r + checkForTranslations(translations, usedUnits, ed, id+"/label", "label"); + r = r + checkForTranslations(translations, usedUnits, ed, id+"/short", "short"); + r = r + checkForTranslations(translations, usedUnits, ed, id+"/definition", "definition"); + r = r + checkForTranslations(translations, usedUnits, ed, id+"/comment", "comment"); + r = r + checkForTranslations(translations, usedUnits, ed, id+"/requirements", "requirements"); + r = r + checkForTranslations(translations, usedUnits, ed, id+"/meaningWhenMissing", "meaningWhenMissing"); + r = r + checkForTranslations(translations, usedUnits, ed, id+"/orderMeaning", "orderMeaning"); + // for (ElementDefinitionConstraintComponent con : ed.getConstraint()) { + // addToList(list, lang, con, ed.getId()+"/constraint", "human", con.getHumanElement()); + // } + // if (ed.hasBinding()) { + // addToList(list, lang, ed.getBinding(), ed.getId()+"/b/desc", "description", ed.getBinding().getDescriptionElement()); + // for (ElementDefinitionBindingAdditionalComponent ab : ed.getBinding().getAdditional()) { + // addToList(list, lang, ab, ed.getId()+"/ab/doco", "documentation", ab.getDocumentationElement()); + // addToList(list, lang, ab, ed.getId()+"/ab/short", "shortDoco", ab.getShortDocoElement()); + // } + // } + } + } + return r; + } + + private int checkForTranslations(List translations, Set usedUnits, Element context, String tname, String pname) { + int r = 0; + Element child = context.getNamedChild(pname); + if (child != null) { + String v = child.primitiveValue(); + if (v != null) { + for (TranslationUnit tu : translations) { + if (tname.equals(tu.getId()) && v.equals(tu.getSrcText())) { + usedUnits.add(tu); + child.setTranslation(tu.getLanguage(), tu.getTgtText()); + r++; + } + } + } + } + return r; + } + private int importFromTranslations(Element parent, Element element, List translations, Set usedUnits) { int t = 0; if (element.isPrimitive() && isTranslatable(element)) { @@ -307,7 +375,7 @@ public class LanguageUtils { } public static boolean handlesAsResource(Resource resource) { - return (resource instanceof CodeSystem && resource.hasUserData(SUPPLEMENT_NAME)); + return (resource instanceof CodeSystem && resource.hasUserData(SUPPLEMENT_NAME)) || (resource instanceof StructureDefinition); } public static boolean handlesAsElement(Element element) { @@ -316,13 +384,55 @@ public class LanguageUtils { public static List generateTranslations(Resource res, String lang) { List list = new ArrayList<>(); - CodeSystem cs = (CodeSystem) res; - for (ConceptDefinitionComponent cd : cs.getConcept()) { - generateTranslations(list, cd, lang); + if (res instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) res; + generateTranslations(list, sd, lang); + } else { + CodeSystem cs = (CodeSystem) res; + for (ConceptDefinitionComponent cd : cs.getConcept()) { + generateTranslations(list, cd, lang); + } } return list; } + private static void generateTranslations(List list, StructureDefinition sd, String lang) { + addToList(list, lang, sd, "name", "name", sd.getNameElement()); + addToList(list, lang, sd, "title", "title", sd.getTitleElement()); + addToList(list, lang, sd, "publisher", "publisher", sd.getPublisherElement()); + for (ContactDetail cd : sd.getContact()) { + addToList(list, lang, cd, "contact.name", "name", cd.getNameElement()); + } + addToList(list, lang, sd, "purpose", "purpose", sd.getPurposeElement()); + addToList(list, lang, sd, "copyright", "copyright", sd.getCopyrightElement()); + for (ElementDefinition ed : sd.getDifferential().getElement()) { + addToList(list, lang, ed, ed.getId()+"/label", "label", ed.getLabelElement()); + addToList(list, lang, ed, ed.getId()+"/short", "short", ed.getShortElement()); + addToList(list, lang, ed, ed.getId()+"/definition", "definition", ed.getDefinitionElement()); + addToList(list, lang, ed, ed.getId()+"/comment", "comment", ed.getCommentElement()); + addToList(list, lang, ed, ed.getId()+"/requirements", "requirements", ed.getRequirementsElement()); + addToList(list, lang, ed, ed.getId()+"/meaningWhenMissing", "meaningWhenMissing", ed.getMeaningWhenMissingElement()); + addToList(list, lang, ed, ed.getId()+"/orderMeaning", "orderMeaning", ed.getOrderMeaningElement()); + for (ElementDefinitionConstraintComponent con : ed.getConstraint()) { + addToList(list, lang, con, ed.getId()+"/constraint", "human", con.getHumanElement()); + } + if (ed.hasBinding()) { + addToList(list, lang, ed.getBinding(), ed.getId()+"/b/desc", "description", ed.getBinding().getDescriptionElement()); + for (ElementDefinitionBindingAdditionalComponent ab : ed.getBinding().getAdditional()) { + addToList(list, lang, ab, ed.getId()+"/ab/doco", "documentation", ab.getDocumentationElement()); + addToList(list, lang, ab, ed.getId()+"/ab/short", "shortDoco", ab.getShortDocoElement()); + } + } + } + } + + private static void addToList(List list, String lang, Base ctxt, String name, String propName, DataType value) { + if (value != null && value.hasPrimitiveValue()) { + list.add(new TranslationUnit(lang, name, ctxt.getNamedProperty(propName).getDefinition(), value.primitiveValue(), value.getTranslation(lang))); + } + + } + private static void generateTranslations(List list, ConceptDefinitionComponent cd, String lang) { String code = cd.getCode(); String display = cd.getDisplay(); @@ -352,7 +462,6 @@ public class LanguageUtils { } } - public static List generateTranslations(Element e, String lang) { List list = new ArrayList<>(); generateTranslations(e, lang, list); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/DataType.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/DataType.java index 7db305055..808d3bb22 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/DataType.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/DataType.java @@ -4,19 +4,19 @@ package org.hl7.fhir.r5.model; /* Copyright (c) 2011+, HL7, Inc. All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, \ are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this \ + + * Redistributions of source code must retain the above copyright notice, this \ list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, \ + * Redistributions in binary form must reproduce the above copyright notice, \ this list of conditions and the following disclaimer in the documentation \ and/or other materials provided with the distribution. - * Neither the name of HL7 nor the names of its contributors may be used to + * Neither the name of HL7 nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND \ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \ @@ -27,7 +27,7 @@ package org.hl7.fhir.r5.model; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \ POSSIBILITY OF SUCH DAMAGE. - */ + */ // Generated on Thu, Mar 23, 2023 19:59+1100 for FHIR v5.0.0 @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import org.hl7.fhir.r5.model.Enumerations.*; +import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.instance.model.api.IBaseDatatypeElement; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.instance.model.api.ICompositeType; @@ -52,26 +53,40 @@ import ca.uhn.fhir.model.api.IElement; @DatatypeDef(name="DataType") public abstract class DataType extends Element implements IBaseDatatype, IElement { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; /** * Constructor */ - public DataType() { - super(); - } + public DataType() { + super(); + } public String fhirType() { return "DataType"; } - public abstract DataType copy(); + public abstract DataType copy(); - public void copyValues(DataType dst) { - super.copyValues(dst); + public void copyValues(DataType dst) { + super.copyValues(dst); + } + + + public String getTranslation(String l) throws FHIRException { + for (Extension e : getExtension()) { + if (e.getUrl().equals(ToolingExtensions.EXT_TRANSLATION)) { + String lang = ToolingExtensions.readStringExtension(e, "lang"); + if (lang.equals(l)) + return e.getExtensionString("content"); } - - + } + return null; + } + + public boolean isTranslatable() { + return false; + } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/MarkdownType.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/MarkdownType.java index b632ebfc9..2e0463520 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/MarkdownType.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/MarkdownType.java @@ -79,4 +79,9 @@ public class MarkdownType extends StringType implements Comparable return "markdown"; } + @Override + public boolean isTranslatable() { + return true; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/StringType.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/StringType.java index 63a9e6186..3a1f86934 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/StringType.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/StringType.java @@ -99,15 +99,8 @@ public class StringType extends PrimitiveType { return "string"; } - public String getTranslation(String l) throws FHIRException { - for (Extension e : getExtension()) { - if (e.getUrl().equals(ToolingExtensions.EXT_TRANSLATION)) { - String lang = ToolingExtensions.readStringExtension(e, "lang"); - if (lang.equals(l)) - return e.getExtensionString("content"); - } - } - return null; + @Override + public boolean isTranslatable() { + return true; } - } \ No newline at end of file