Beispiel #1
0
  /** {@inheritDoc} not needed in Testserver */
  public UriDt post(IResource res) {

    log.info(res.getClass().toString());
    String resURI = "http://www.test-server.de/" + res.getClass().getSimpleName() + "/" + resNumber;
    UriDt setUri = new UriDt(resURI);
    log.info("TestSever Created ID: " + resURI);
    resMap.put(resURI, res);
    resNumber++;
    return setUri;
  }
 private String parseNarrative(
     HomeRequest theRequest, EncodingEnum theCtEnum, String theResultBody) {
   try {
     IBaseResource par = theCtEnum.newParser(getContext(theRequest)).parseResource(theResultBody);
     String retVal;
     if (par instanceof IResource) {
       IResource resource = (IResource) par;
       retVal = resource.getText().getDiv().getValueAsString();
     } else if (par instanceof IDomainResource) {
       retVal = ((IDomainResource) par).getText().getDivAsString();
     } else {
       retVal = null;
     }
     return StringUtils.defaultString(retVal);
   } catch (Exception e) {
     ourLog.error("Failed to parse resource", e);
     return "";
   }
 }
Beispiel #3
0
  private void encodeResourceToXmlStreamWriter(
      IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource)
      throws XMLStreamException, DataFormatException {
    String resourceId = null;
    if (theResource instanceof IResource) {
      // HAPI structs
      IResource iResource = (IResource) theResource;
      if (StringUtils.isNotBlank(iResource.getId().getValue())) {
        resourceId = iResource.getId().getIdPart();
      }
    } else {
      // HL7 structs
      IAnyResource resource = (IAnyResource) theResource;
      if (StringUtils.isNotBlank(resource.getId())) {
        resourceId = resource.getId();
      }
    }

    encodeResourceToXmlStreamWriter(theResource, theEventWriter, theIncludedResource, resourceId);
  }
Beispiel #4
0
 @Override
 public IDeleteTyped resource(IResource theResource) {
   Validate.notNull(theResource, "theResource can not be null");
   IdDt id = theResource.getId();
   Validate.notNull(id, "theResource.getId() can not be null");
   if (id.hasResourceType() == false || id.hasIdPart() == false) {
     throw new IllegalArgumentException(
         "theResource.getId() must contain a resource type and logical ID at a minimum (e.g. Patient/1234), found: "
             + id.getValue());
   }
   myId = id;
   return this;
 }
Beispiel #5
0
  /**
   * @notice In Fhir model, {@link Patient} has a collection of names, while in this extension
   *     table, {@link PersonComplement}, there is only one name for each {@link Person}.
   */
  @Override
  public IResourceEntity constructEntityFromResource(IResource resource) {
    super.constructEntityFromResource(resource);
    if (resource instanceof Patient) {
      Patient patient = (Patient) resource;

      Iterator<HumanNameDt> iterator = patient.getName().iterator();
      // while(iterator.hasNext()){
      if (iterator.hasNext()) {
        HumanNameDt next = iterator.next();
        this.givenName1 =
            next.getGiven()
                .get(0)
                .getValue(); // the next method was not advancing to the next element, then the need
        // to use the get(index) method
        if (next.getGiven().size()
            > 1) // TODO add unit tests, to assure this won't be changed to hasNext
        this.givenName2 = next.getGiven().get(1).getValue();
        Iterator<StringDt> family = next.getFamily().iterator();
        this.familyName = "";
        while (family.hasNext()) {
          this.familyName = this.familyName.concat(family.next().getValue() + " ");
        }
        if (next.getSuffix().iterator().hasNext())
          this.suffixName = next.getSuffix().iterator().next().getValue();
        if (next.getPrefix().iterator().hasNext())
          this.prefixName = next.getPrefix().iterator().next().getValue();
      }
      // }

      this.active = patient.getActive();
      // MARITAL STATUS
      //
      //	this.maritalStatus.setId(OmopConceptMapping.getInstance().get(OmopConceptMapping.MARITAL_STATUS, patient.getMaritalStatus().getText()));
    } else {
      ourLog.error(
          "There was not possible to construct the entity ? using the resource ?. It should be used the resource ?.",
          this.getClass().getSimpleName(),
          resource.getResourceName(),
          getResourceType());
    }
    return this;
  }
Beispiel #6
0
    @Override
    public MethodOutcome execute() {
      if (myResource == null) {
        myResource = parseResourceBody(myResourceBody);
      }
      if (myId == null) {
        myId = myResource.getId();
      }
      if (myId == null || myId.hasIdPart() == false) {
        throw new InvalidRequestException(
            "No ID supplied for resource to update, can not invoke server");
      }

      BaseHttpClientInvocation invocation =
          MethodUtil.createUpdateInvocation(myResource, myResourceBody, myId, myContext);

      RuntimeResourceDefinition def = myContext.getResourceDefinition(myResource);
      final String resourceName = def.getName();

      OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);

      Map<String, List<String>> params = new HashMap<String, List<String>>();
      return invoke(params, binding, invocation);
    }
  @SuppressWarnings("unchecked")
  @Override
  public Object invokeServer(
      IRestfulServer theServer, RequestDetails theRequest, Object[] theMethodParams)
      throws InvalidRequestException, InternalErrorException {

    /*
     * The design of HAPI's transaction method for DSTU1 support assumed that a transaction was just an update on a
     * bunch of resources (because that's what it was), but in DSTU2 transaction has become much more broad, so we
     * no longer hold the user's hand much here.
     */
    if (myTransactionParamStyle == ParamStyle.RESOURCE_BUNDLE) {
      // This is the DSTU2 style
      Object response = invokeServerMethod(theServer, theRequest, theMethodParams);
      return response;
    }

    // Grab the IDs of all of the resources in the transaction
    List<IResource> resources;
    if (theMethodParams[myTransactionParamIndex] instanceof Bundle) {
      resources = ((Bundle) theMethodParams[myTransactionParamIndex]).toListOfResources();
    } else {
      resources = (List<IResource>) theMethodParams[myTransactionParamIndex];
    }

    IdentityHashMap<IResource, IdDt> oldIds = new IdentityHashMap<IResource, IdDt>();
    for (IResource next : resources) {
      oldIds.put(next, next.getId());
    }

    // Call the server implementation method
    Object response = invokeServerMethod(theServer, theRequest, theMethodParams);
    IBundleProvider retVal = toResourceList(response);

    /*
     * int offset = 0; if (retVal.size() != resources.size()) { if (retVal.size() > 0 && retVal.getResources(0,
     * 1).get(0) instanceof OperationOutcome) { offset = 1; } else { throw new
     * InternalErrorException("Transaction bundle contained " + resources.size() +
     * " entries, but server method response contained " + retVal.size() + " entries (must be the same)"); } }
     */

    List<IBaseResource> retResources = retVal.getResources(0, retVal.size());
    for (int i = 0; i < retResources.size(); i++) {
      IdDt oldId = oldIds.get(retResources.get(i));
      IBaseResource newRes = retResources.get(i);
      if (newRes.getIdElement() == null || newRes.getIdElement().isEmpty()) {
        if (!(newRes instanceof BaseOperationOutcome)) {
          throw new InternalErrorException(
              "Transaction method returned resource at index "
                  + i
                  + " with no id specified - IResource#setId(IdDt)");
        }
      }

      if (oldId != null && !oldId.isEmpty()) {
        if (!oldId.equals(newRes.getIdElement()) && newRes instanceof IResource) {
          ((IResource) newRes)
              .getResourceMetadata()
              .put(ResourceMetadataKeyEnum.PREVIOUS_ID, oldId);
        }
      }
    }

    return retVal;
  }
Beispiel #8
0
  private void encodeResourceToXmlStreamWriter(
      IBaseResource theResource,
      XMLStreamWriter theEventWriter,
      boolean theContainedResource,
      String theResourceId)
      throws XMLStreamException {
    if (!theContainedResource) {
      super.containResourcesForEncoding(theResource);
    }

    RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
    if (resDef == null) {
      throw new ConfigurationException("Unknown resource type: " + theResource.getClass());
    }

    theEventWriter.writeStartElement(resDef.getName());
    theEventWriter.writeDefaultNamespace(FHIR_NS);

    if (theResource instanceof IAnyResource) {

      // HL7.org Structures
      encodeCompositeElementToStreamWriter(
          theResource, theResource, theEventWriter, resDef, theContainedResource);

    } else {

      if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {

        // DSTU2+

        IResource resource = (IResource) theResource;
        writeOptionalTagWithValue(theEventWriter, "id", theResourceId);

        InstantDt updated =
            (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
        IdDt resourceId = resource.getId();
        String versionIdPart = resourceId.getVersionIdPart();
        if (isBlank(versionIdPart)) {
          versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
        }
        List<BaseCodingDt> securityLabels =
            extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
        List<IdDt> profiles =
            extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
        TagList tags = ResourceMetadataKeyEnum.TAG_LIST.get(resource);
        if (ElementUtil.isEmpty(versionIdPart, updated, securityLabels, profiles) == false) {
          theEventWriter.writeStartElement("meta");
          writeOptionalTagWithValue(theEventWriter, "versionId", versionIdPart);
          if (updated != null) {
            writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
          }

          for (IdDt profile : profiles) {
            theEventWriter.writeStartElement("profile");
            theEventWriter.writeAttribute("value", profile.getValue());
            theEventWriter.writeEndElement();
          }
          for (BaseCodingDt securityLabel : securityLabels) {
            theEventWriter.writeStartElement("security");
            BaseRuntimeElementCompositeDefinition<?> def =
                (BaseRuntimeElementCompositeDefinition<?>)
                    myContext.getElementDefinition(securityLabel.getClass());
            encodeCompositeElementChildrenToStreamWriter(
                resource, securityLabel, theEventWriter, def.getChildren(), theContainedResource);
            theEventWriter.writeEndElement();
          }
          if (tags != null) {
            for (Tag tag : tags) {
              theEventWriter.writeStartElement("tag");
              writeOptionalTagWithValue(theEventWriter, "system", tag.getScheme());
              writeOptionalTagWithValue(theEventWriter, "code", tag.getTerm());
              writeOptionalTagWithValue(theEventWriter, "display", tag.getLabel());
              theEventWriter.writeEndElement();
            }
          }
          theEventWriter.writeEndElement();
        }

        if (theResource instanceof IBaseBinary) {
          IBaseBinary bin = (IBaseBinary) theResource;
          writeOptionalTagWithValue(theEventWriter, "contentType", bin.getContentType());
          writeOptionalTagWithValue(theEventWriter, "content", bin.getContentAsBase64());
        } else {
          encodeResourceToStreamWriterInDstu2Format(
              resDef, theResource, theResource, theEventWriter, resDef, theContainedResource);
        }

      } else {

        // DSTU1
        if (theResourceId != null && theContainedResource) {
          theEventWriter.writeAttribute("id", theResourceId);
        }

        if (theResource instanceof IBaseBinary) {
          IBaseBinary bin = (IBaseBinary) theResource;
          if (bin.getContentType() != null) {
            theEventWriter.writeAttribute("contentType", bin.getContentType());
          }
          theEventWriter.writeCharacters(bin.getContentAsBase64());
        } else {
          encodeCompositeElementToStreamWriter(
              theResource, theResource, theEventWriter, resDef, theContainedResource);
        }
      }
    }

    theEventWriter.writeEndElement();
  }
Beispiel #9
0
  private void encodeBundleToWriterDstu2(Bundle theBundle, XMLStreamWriter theEventWriter)
      throws XMLStreamException {
    theEventWriter.writeStartElement("Bundle");
    theEventWriter.writeDefaultNamespace(FHIR_NS);

    writeOptionalTagWithValue(theEventWriter, "id", theBundle.getId().getIdPart());

    InstantDt updated =
        (InstantDt) theBundle.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
    IdDt bundleId = theBundle.getId();
    if (bundleId != null && isNotBlank(bundleId.getVersionIdPart())
        || (updated != null && !updated.isEmpty())) {
      theEventWriter.writeStartElement("meta");
      writeOptionalTagWithValue(theEventWriter, "versionId", bundleId.getVersionIdPart());
      if (updated != null) {
        writeOptionalTagWithValue(theEventWriter, "lastUpdated", updated.getValueAsString());
      }
      theEventWriter.writeEndElement();
    }

    String bundleBaseUrl = theBundle.getLinkBase().getValue();

    writeOptionalTagWithValue(theEventWriter, "type", theBundle.getType().getValue());
    writeOptionalTagWithValue(theEventWriter, "base", bundleBaseUrl);
    writeOptionalTagWithValue(
        theEventWriter, "total", theBundle.getTotalResults().getValueAsString());

    writeBundleResourceLink(theEventWriter, "first", theBundle.getLinkFirst());
    writeBundleResourceLink(theEventWriter, "previous", theBundle.getLinkPrevious());
    writeBundleResourceLink(theEventWriter, "next", theBundle.getLinkNext());
    writeBundleResourceLink(theEventWriter, "last", theBundle.getLinkLast());
    writeBundleResourceLink(theEventWriter, "self", theBundle.getLinkSelf());

    for (BundleEntry nextEntry : theBundle.getEntries()) {
      theEventWriter.writeStartElement("entry");

      boolean deleted = false;
      if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
        deleted = true;
      }

      writeOptionalTagWithValue(
          theEventWriter, "base", determineResourceBaseUrl(bundleBaseUrl, nextEntry));

      IResource resource = nextEntry.getResource();
      if (resource != null && !resource.isEmpty() && !deleted) {
        theEventWriter.writeStartElement("resource");
        encodeResourceToXmlStreamWriter(resource, theEventWriter, false);
        theEventWriter.writeEndElement(); // content
      } else {
        ourLog.debug("Bundle entry contains null resource");
      }

      if (nextEntry.getSearchMode().isEmpty() == false || nextEntry.getScore().isEmpty() == false) {
        theEventWriter.writeStartElement("search");
        writeOptionalTagWithValue(
            theEventWriter, "mode", nextEntry.getSearchMode().getValueAsString());
        writeOptionalTagWithValue(theEventWriter, "score", nextEntry.getScore().getValueAsString());
        theEventWriter.writeEndElement();
        // IResource nextResource = nextEntry.getResource();
      }

      if (nextEntry.getTransactionMethod().isEmpty() == false
          || nextEntry.getLinkSearch().isEmpty() == false) {
        theEventWriter.writeStartElement("transaction");
        writeOptionalTagWithValue(
            theEventWriter, "method", nextEntry.getTransactionMethod().getValue());
        writeOptionalTagWithValue(theEventWriter, "url", nextEntry.getLinkSearch().getValue());
        theEventWriter.writeEndElement();
      }

      if (deleted) {
        theEventWriter.writeStartElement("deleted");
        writeOptionalTagWithValue(theEventWriter, "type", nextEntry.getId().getResourceType());
        writeOptionalTagWithValue(theEventWriter, "id", nextEntry.getId().getIdPart());
        writeOptionalTagWithValue(
            theEventWriter, "versionId", nextEntry.getId().getVersionIdPart());
        writeOptionalTagWithValue(
            theEventWriter, "instant", nextEntry.getDeletedAt().getValueAsString());
        theEventWriter.writeEndElement();
      }

      theEventWriter.writeEndElement(); // entry
    }

    theEventWriter.writeEndElement();
    theEventWriter.close();
  }
Beispiel #10
0
  private void encodeBundleToWriterDstu1(Bundle theBundle, XMLStreamWriter eventWriter)
      throws XMLStreamException {
    eventWriter.writeStartElement("feed");
    eventWriter.writeDefaultNamespace(ATOM_NS);

    writeTagWithTextNode(eventWriter, "title", theBundle.getTitle());
    writeTagWithTextNode(eventWriter, "id", theBundle.getBundleId());

    writeAtomLink(eventWriter, Constants.LINK_SELF, theBundle.getLinkSelf());
    writeAtomLink(eventWriter, Constants.LINK_FIRST, theBundle.getLinkFirst());
    writeAtomLink(eventWriter, Constants.LINK_PREVIOUS, theBundle.getLinkPrevious());
    writeAtomLink(eventWriter, Constants.LINK_NEXT, theBundle.getLinkNext());
    writeAtomLink(eventWriter, Constants.LINK_LAST, theBundle.getLinkLast());
    writeAtomLink(eventWriter, Constants.LINK_FHIR_BASE, theBundle.getLinkBase());

    if (theBundle.getTotalResults().getValue() != null) {
      eventWriter.writeStartElement("os", "totalResults", OPENSEARCH_NS);
      eventWriter.writeNamespace("os", OPENSEARCH_NS);
      eventWriter.writeCharacters(theBundle.getTotalResults().getValue().toString());
      eventWriter.writeEndElement();
    }

    writeOptionalTagWithTextNode(eventWriter, "updated", theBundle.getUpdated());

    if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) {
      eventWriter.writeStartElement("author");
      writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName());
      writeOptionalTagWithTextNode(eventWriter, "uri", theBundle.getAuthorUri());
      eventWriter.writeEndElement();
    }

    writeCategories(eventWriter, theBundle.getCategories());

    for (BundleEntry nextEntry : theBundle.getEntries()) {
      boolean deleted = false;
      if (nextEntry.getDeletedAt() != null && nextEntry.getDeletedAt().isEmpty() == false) {
        deleted = true;
        eventWriter.writeStartElement("at", "deleted-entry", TOMBSTONES_NS);
        eventWriter.writeNamespace("at", TOMBSTONES_NS);

        if (nextEntry.getDeletedResourceId().isEmpty()) {
          writeOptionalAttribute(eventWriter, "ref", nextEntry.getId().getValueAsString());
        } else {
          writeOptionalAttribute(
              eventWriter, "ref", nextEntry.getDeletedResourceId().getValueAsString());
        }

        writeOptionalAttribute(eventWriter, "when", nextEntry.getDeletedAt().getValueAsString());
        if (nextEntry.getDeletedByEmail().isEmpty() == false
            || nextEntry.getDeletedByName().isEmpty() == false) {
          eventWriter.writeStartElement(TOMBSTONES_NS, "by");
          if (nextEntry.getDeletedByName().isEmpty() == false) {
            eventWriter.writeStartElement(TOMBSTONES_NS, "name");
            eventWriter.writeCharacters(nextEntry.getDeletedByName().getValue());
            eventWriter.writeEndElement();
          }
          if (nextEntry.getDeletedByEmail().isEmpty() == false) {
            eventWriter.writeStartElement(TOMBSTONES_NS, "email");
            eventWriter.writeCharacters(nextEntry.getDeletedByEmail().getValue());
            eventWriter.writeEndElement();
          }
          eventWriter.writeEndElement();
        }
        if (nextEntry.getDeletedComment().isEmpty() == false) {
          eventWriter.writeStartElement(TOMBSTONES_NS, "comment");
          eventWriter.writeCharacters(nextEntry.getDeletedComment().getValue());
          eventWriter.writeEndElement();
        }
      } else {
        eventWriter.writeStartElement("entry");
      }

      writeOptionalTagWithTextNode(eventWriter, "title", nextEntry.getTitle());
      if (!deleted) {
        if (nextEntry.getId().isEmpty() == false) {
          writeTagWithTextNode(eventWriter, "id", nextEntry.getId());
        } else {
          writeTagWithTextNode(eventWriter, "id", nextEntry.getResource().getId());
        }
      }
      writeOptionalTagWithTextNode(eventWriter, "updated", nextEntry.getUpdated());
      writeOptionalTagWithTextNode(eventWriter, "published", nextEntry.getPublished());

      writeCategories(eventWriter, nextEntry.getCategories());

      if (!nextEntry.getLinkSelf().isEmpty()) {
        writeAtomLink(eventWriter, "self", nextEntry.getLinkSelf());
      }

      if (!nextEntry.getLinkAlternate().isEmpty()) {
        writeAtomLink(eventWriter, "alternate", nextEntry.getLinkAlternate());
      }

      if (!nextEntry.getLinkSearch().isEmpty()) {
        writeAtomLink(eventWriter, "search", nextEntry.getLinkSearch());
      }

      IResource resource = nextEntry.getResource();
      if (resource != null && !resource.isEmpty() && !deleted) {
        eventWriter.writeStartElement("content");
        eventWriter.writeAttribute("type", "text/xml");
        encodeResourceToXmlStreamWriter(resource, eventWriter, false);
        eventWriter.writeEndElement(); // content
      } else {
        ourLog.debug("Bundle entry contains null resource");
      }

      if (!nextEntry.getSummary().isEmpty()) {
        eventWriter.writeStartElement("summary");
        eventWriter.writeAttribute("type", "xhtml");
        encodeXhtml(nextEntry.getSummary(), eventWriter);
        eventWriter.writeEndElement();
      }

      eventWriter.writeEndElement(); // entry
    }

    eventWriter.writeEndElement();
    eventWriter.close();
  }
  @Transactional(propagation = Propagation.REQUIRED)
  @Override
  public List<IResource> transaction(
      RequestDetails theRequestDetails, List<IResource> theResources) {
    ourLog.info("Beginning transaction with {} resources", theResources.size());

    // Notify interceptors
    ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
    notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);

    long start = System.currentTimeMillis();

    Set<IdDt> allIds = new HashSet<IdDt>();

    for (int i = 0; i < theResources.size(); i++) {
      IResource res = theResources.get(i);
      if (res.getId().hasIdPart()
          && !res.getId().hasResourceType()
          && !isPlaceholder(res.getId())) {
        res.setId(new IdDt(toResourceName(res.getClass()), res.getId().getIdPart()));
      }

      /*
       * Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
       */
      if (isPlaceholder(res.getId())) {
        if (!allIds.add(res.getId())) {
          throw new InvalidRequestException(
              "Transaction bundle contains multiple resources with ID: " + res.getId());
        }
      } else if (res.getId().hasResourceType() && res.getId().hasIdPart()) {
        IdDt nextId = res.getId().toUnqualifiedVersionless();
        if (!allIds.add(nextId)) {
          throw new InvalidRequestException(
              "Transaction bundle contains multiple resources with ID: " + nextId);
        }
      }
    }

    FhirTerser terser = getContext().newTerser();

    int creations = 0;
    int updates = 0;

    Map<IdDt, IdDt> idConversions = new HashMap<IdDt, IdDt>();

    List<ResourceTable> persistedResources = new ArrayList<ResourceTable>();

    List<IResource> retVal = new ArrayList<IResource>();
    OperationOutcome oo = new OperationOutcome();
    retVal.add(oo);

    Date updateTime = new Date();
    for (int resourceIdx = 0; resourceIdx < theResources.size(); resourceIdx++) {
      IResource nextResource = theResources.get(resourceIdx);

      IdDt nextId = nextResource.getId();
      if (nextId == null) {
        nextId = new IdDt();
      }

      String resourceName = toResourceName(nextResource);
      BundleEntryTransactionMethodEnum nextResouceOperationIn =
          ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.get(nextResource);
      if (nextResouceOperationIn == null
          && hasValue(ResourceMetadataKeyEnum.DELETED_AT.get(nextResource))) {
        nextResouceOperationIn = BundleEntryTransactionMethodEnum.DELETE;
      }

      String matchUrl = ResourceMetadataKeyEnum.LINK_SEARCH.get(nextResource);
      Set<Long> candidateMatches = null;
      if (StringUtils.isNotBlank(matchUrl)) {
        candidateMatches = processMatchUrl(matchUrl, nextResource.getClass());
      }

      ResourceTable entity;
      if (nextResouceOperationIn == BundleEntryTransactionMethodEnum.POST) {
        entity = null;
      } else if (nextResouceOperationIn == BundleEntryTransactionMethodEnum.PUT
          || nextResouceOperationIn == BundleEntryTransactionMethodEnum.DELETE) {
        if (candidateMatches == null || candidateMatches.size() == 0) {
          if (nextId == null || StringUtils.isBlank(nextId.getIdPart())) {
            throw new InvalidRequestException(
                getContext()
                    .getLocalizer()
                    .getMessage(
                        BaseHapiFhirSystemDao.class,
                        "transactionOperationFailedNoId",
                        nextResouceOperationIn.name()));
          }
          entity = tryToLoadEntity(nextId);
          if (entity == null) {
            if (nextResouceOperationIn == BundleEntryTransactionMethodEnum.PUT) {
              ourLog.debug(
                  "Attempting to UPDATE resource with unknown ID '{}', will CREATE instead",
                  nextId);
            } else if (candidateMatches == null) {
              throw new InvalidRequestException(
                  getContext()
                      .getLocalizer()
                      .getMessage(
                          BaseHapiFhirSystemDao.class,
                          "transactionOperationFailedUnknownId",
                          nextResouceOperationIn.name(),
                          nextId));
            } else {
              ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
              persistedResources.add(null);
              retVal.add(nextResource);
              continue;
            }
          }
        } else if (candidateMatches.size() == 1) {
          entity = loadFirstEntityFromCandidateMatches(candidateMatches);
        } else {
          throw new InvalidRequestException(
              getContext()
                  .getLocalizer()
                  .getMessage(
                      BaseHapiFhirSystemDao.class,
                      "transactionOperationWithMultipleMatchFailure",
                      nextResouceOperationIn.name(),
                      matchUrl,
                      candidateMatches.size()));
        }
      } else if (nextId.isEmpty() || isPlaceholder(nextId)) {
        entity = null;
      } else {
        entity = tryToLoadEntity(nextId);
      }

      BundleEntryTransactionMethodEnum nextResouceOperationOut;
      if (entity == null) {
        nextResouceOperationOut = BundleEntryTransactionMethodEnum.POST;
        entity = toEntity(nextResource);
        entity.setUpdated(updateTime);
        entity.setPublished(updateTime);
        if (nextId.isEmpty() == false && "cid:".equals(nextId.getBaseUrl())) {
          ourLog.debug(
              "Resource in transaction has ID[{}], will replace with server assigned ID",
              nextId.getIdPart());
        } else if (nextResouceOperationIn == BundleEntryTransactionMethodEnum.POST) {
          if (nextId.isEmpty() == false) {
            ourLog.debug(
                "Resource in transaction has ID[{}] but is marked for CREATE, will ignore ID",
                nextId.getIdPart());
          }
          if (candidateMatches != null) {
            if (candidateMatches.size() == 1) {
              ourLog.debug("Resource with match URL [{}] already exists, will be NOOP", matchUrl);
              BaseHasResource existingEntity =
                  loadFirstEntityFromCandidateMatches(candidateMatches);
              IResource existing = (IResource) toResource(existingEntity, false);
              persistedResources.add(null);
              retVal.add(existing);
              continue;
            }
            if (candidateMatches.size() > 1) {
              throw new InvalidRequestException(
                  getContext()
                      .getLocalizer()
                      .getMessage(
                          BaseHapiFhirSystemDao.class,
                          "transactionOperationWithMultipleMatchFailure",
                          BundleEntryTransactionMethodEnum.POST.name(),
                          matchUrl,
                          candidateMatches.size()));
            }
          }
        } else {
          createForcedIdIfNeeded(entity, nextId);
        }
        myEntityManager.persist(entity);
        if (entity.getForcedId() != null) {
          myEntityManager.persist(entity.getForcedId());
        }
        creations++;
        ourLog.info(
            "Resource Type[{}] with ID[{}] does not exist, creating it", resourceName, nextId);
      } else {
        nextResouceOperationOut = nextResouceOperationIn;
        if (nextResouceOperationOut == null) {
          nextResouceOperationOut = BundleEntryTransactionMethodEnum.PUT;
        }
        updates++;
        ourLog.info("Resource Type[{}] with ID[{}] exists, updating it", resourceName, nextId);
      }

      persistedResources.add(entity);
      retVal.add(nextResource);
      ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.put(nextResource, nextResouceOperationOut);
    }

    ourLog.info("Flushing transaction to database");
    myEntityManager.flush();

    for (int i = 0; i < persistedResources.size(); i++) {
      ResourceTable entity = persistedResources.get(i);

      String resourceName = toResourceName(theResources.get(i));
      IdDt nextId = theResources.get(i).getId();

      IdDt newId;

      if (entity == null) {
        newId = retVal.get(i + 1).getId().toUnqualifiedVersionless();
      } else {
        newId = entity.getIdDt().toUnqualifiedVersionless();
      }

      if (nextId == null || nextId.isEmpty()) {
        ourLog.info(
            "Transaction resource (with no preexisting ID) has been assigned new ID[{}]",
            nextId,
            newId);
      } else {
        if (nextId.toUnqualifiedVersionless().equals(newId)) {
          ourLog.info("Transaction resource ID[{}] is being updated", newId);
        } else {
          if (isPlaceholder(nextId)) {
            // nextId = new IdDt(resourceName, nextId.getIdPart());
            ourLog.info("Transaction resource ID[{}] has been assigned new ID[{}]", nextId, newId);
            idConversions.put(nextId, newId);
            idConversions.put(new IdDt(resourceName + "/" + nextId.getValue()), newId);
          }
        }
      }
    }

    for (IResource nextResource : theResources) {
      List<BaseResourceReferenceDt> allRefs =
          terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
      for (BaseResourceReferenceDt nextRef : allRefs) {
        IdDt nextId = nextRef.getReference();
        if (idConversions.containsKey(nextId)) {
          IdDt newId = idConversions.get(nextId);
          ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
          nextRef.setReference(newId);
        } else {
          ourLog.debug(" * Reference [{}] does not exist in bundle", nextId);
        }
      }
    }

    ourLog.info("Re-flushing updated resource references and extracting search criteria");

    for (int i = 0; i < theResources.size(); i++) {
      IResource resource = theResources.get(i);
      ResourceTable table = persistedResources.get(i);
      if (table == null) {
        continue;
      }

      InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(resource);
      Date deletedTimestampOrNull =
          deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
      if (deletedInstantOrNull == null
          && ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.get(resource)
              == BundleEntryTransactionMethodEnum.DELETE) {
        deletedTimestampOrNull = updateTime;
        ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull));
      }

      updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull, updateTime);
    }

    long delay = System.currentTimeMillis() - start;
    ourLog.info(
        "Transaction completed in {}ms with {} creations and {} updates",
        new Object[] {delay, creations, updates});

    oo.addIssue()
        .setSeverity(IssueSeverityEnum.INFORMATION)
        .setDetails(
            "Transaction completed in "
                + delay
                + "ms with "
                + creations
                + " creations and "
                + updates
                + " updates");

    return retVal;
  }
  @Override
  public Object invokeClient(
      String theResponseMimeType,
      Reader theResponseReader,
      int theResponseStatusCode,
      Map<String, List<String>> theHeaders)
      throws IOException {
    IParser parser =
        createAppropriateParserForParsingResponse(
            theResponseMimeType, theResponseReader, theResponseStatusCode);

    switch (getReturnType()) {
      case BUNDLE:
        {
          Bundle bundle;
          if (myResourceType != null) {
            bundle = parser.parseBundle(myResourceType, theResponseReader);
          } else {
            bundle = parser.parseBundle(theResponseReader);
          }
          switch (getMethodReturnType()) {
            case BUNDLE:
              return bundle;
            case LIST_OF_RESOURCES:
              List<IResource> listOfResources;
              if (myResourceListCollectionType != null) {
                listOfResources = new ArrayList<IResource>();
                for (IResource next : bundle.toListOfResources()) {
                  if (!myResourceListCollectionType.isAssignableFrom(next.getClass())) {
                    ourLog.debug(
                        "Not returning resource of type {} because it is not a subclass or instance of {}",
                        next.getClass(),
                        myResourceListCollectionType);
                    continue;
                  }
                  listOfResources.add(next);
                }
              } else {
                listOfResources = bundle.toListOfResources();
              }
              return listOfResources;
            case RESOURCE:
              List<IResource> list = bundle.toListOfResources();
              if (list.size() == 0) {
                return null;
              } else if (list.size() == 1) {
                return list.get(0);
              } else {
                throw new InvalidResponseException(
                    theResponseStatusCode,
                    "FHIR server call returned a bundle with multiple resources, but this method is only able to returns one.");
              }
            case BUNDLE_PROVIDER:
              throw new IllegalStateException(
                  "Return type of "
                      + IBundleProvider.class.getSimpleName()
                      + " is not supported in clients");
          }
          break;
        }
      case RESOURCE:
        {
          IResource resource;
          if (myResourceType != null) {
            resource = parser.parseResource(myResourceType, theResponseReader);
          } else {
            resource = parser.parseResource(theResponseReader);
          }

          MethodUtil.parseClientRequestResourceHeaders(null, theHeaders, resource);

          switch (getMethodReturnType()) {
            case BUNDLE:
              return Bundle.withSingleResource(resource);
            case LIST_OF_RESOURCES:
              return Collections.singletonList(resource);
            case RESOURCE:
              return resource;
            case BUNDLE_PROVIDER:
              throw new IllegalStateException(
                  "Return type of "
                      + IBundleProvider.class.getSimpleName()
                      + " is not supported in clients");
          }
          break;
        }
    }

    throw new IllegalStateException("Should not get here!");
  }
 private String getConditionalUrl(IResource resource, IdentifierDt identifier) {
   return resource.getResourceName()
       + "?identifier=".concat(identifier.getSystem()).concat("%7C").concat(identifier.getValue());
 }
Beispiel #14
0
 protected String getPreferredId(IResource theResource, String theId) {
   if (isNotBlank(theId)) {
     return theId;
   }
   return theResource.getId().getIdPart();
 }