001package org.hl7.fhir.r5.utils;
002
003import java.io.IOException;
004
005import org.hl7.fhir.exceptions.FHIRException;
006import org.hl7.fhir.r5.context.ContextUtilities;
007import org.hl7.fhir.r5.context.IWorkerContext;
008import org.hl7.fhir.r5.elementmodel.Element;
009import org.hl7.fhir.r5.model.Base;
010import org.hl7.fhir.r5.model.ElementDefinition;
011import org.hl7.fhir.r5.model.Extension;
012import org.hl7.fhir.r5.model.Property;
013import org.hl7.fhir.r5.model.Resource;
014import org.hl7.fhir.r5.model.StructureDefinition;
015import org.hl7.fhir.utilities.i18n.LanguageFileProducer;
016import org.hl7.fhir.utilities.i18n.LanguageFileProducer.LanguageProducerLanguageSession;
017import org.hl7.fhir.utilities.i18n.LanguageFileProducer.LanguageProducerSession;
018import org.hl7.fhir.utilities.i18n.LanguageFileProducer.TextUnit;
019
020
021public class ResourceLanguageFileBuilder {
022
023  
024  private LanguageFileProducer lp;
025  private String source;
026  private String target;
027  private IWorkerContext context;
028  StructureDefinition profile = null;
029
030  public void prepare(LanguageFileProducer lp, IWorkerContext context, String source, String target) {
031    this.lp = lp;
032    this.source = source;
033    this.target = target;
034    this.context = context;
035  }
036  
037  
038  public StructureDefinition getProfile() {
039    return profile;
040  }
041
042  public void setProfile(StructureDefinition profile) {
043    this.profile = profile;
044  }
045  
046  public void build(Resource res) throws IOException {
047    String id = res.fhirType();
048    String path = res.fhirType() +"-"+res.getIdBase();
049    
050    if (!source.equals(res.getLanguage())) {
051      throw new FHIRException("Language mismatch: '"+source+"' => '"+target+"' but resource language is '"+res.getLanguage()+"'");
052    }
053
054    if (profile == null) {
055      profile = context.fetchTypeDefinition(res.fhirType());
056      if (profile == null) {
057        throw new FHIRException("profile");
058      }
059    }
060
061    LanguageProducerSession session = lp.startSession(path,source);
062    LanguageProducerLanguageSession langSession = session.forLang(target);
063  
064    for (Property p : res.children()) {
065      process(langSession, p, id, path);      
066    }
067    
068    langSession.finish();
069    session.finish();
070  }
071  
072  private void process(LanguageProducerLanguageSession sess, Property p, String id, String path) throws IOException {
073    if (p.hasValues()) {
074      int i = 0;
075      for (Base b : p.getValues()) {
076        String pid = id+"."+p.getName();
077        String ppath = path+"."+p.getName()+(p.isList() ? "["+i+"]" : "");
078        i++;
079        if (isTranslatable(p, b, pid)) {
080          sess.entry(new TextUnit(ppath, getContext(), b.primitiveValue(), getTranslation(b, target)));
081        }
082        for (Property pp : b.children()) {
083          process(sess, pp, pid, ppath);      
084        }
085      }
086    }  
087  }
088
089  private String getContext() {
090    throw new Error("not done yet"); 
091  }
092
093
094  private boolean isTranslatable(Property p, Base b, String id) {
095    if (context.isPrimitiveType(b.fhirType())) { // never any translations for non-primitives
096      ElementDefinition ed = null;
097      for (ElementDefinition t : profile.getSnapshot().getElement()) {
098        if (t.getId().equals(id)) {
099          ed = t;
100        }
101      }
102      if (ed != null && ed.hasExtension(ToolingExtensions.EXT_TRANSLATABLE)) {
103        return true;
104      }
105    }
106    return false;
107  }
108
109  private String getTranslation(Base b, String target2) {
110    if (b instanceof  org.hl7.fhir.r5.model.Element) {
111      org.hl7.fhir.r5.model.Element e = (org.hl7.fhir.r5.model.Element) b;
112      for (Extension ext : e.getExtensionsByUrl(ToolingExtensions.EXT_TRANSLATION)) {
113        String lang = ext.hasExtension("lang") ? ext.getExtensionString("lang") : null;
114        if (target.equals(lang)) {
115          return ext.getExtensionString("content");
116        }
117      }      
118    }
119    return null;
120  }
121
122  public void build(Element res) {
123    
124  }
125
126}