package ca.uhn.fhir.model.api;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.Serializable;
import org.apache.commons.lang3.builder.ToStringBuilder;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
/**
* Represents a FHIR resource path specification, e.g. <code>Patient:name</code>
* <p>
* Note on equality: This class uses {@link #getValue() value} and the {@link #isRecurse() recurse} properties to test
* equality. Prior to HAPI 1.2 (and FHIR DSTU2) the recurse property did not exist, so this may merit consideration when
* upgrading servers.
* </p>
*/
public class Include implements Serializable {
private static final long serialVersionUID = 1L;
private final boolean myImmutable;
private boolean myRecurse;
private String myValue;
/**
* Constructor for <b>non-recursive</b> include
*
* @param theValue
* The <code>_include</code> value, e.g. "Patient:name"
*/
public Include(String theValue) {
myValue = theValue;
myImmutable = false;
}
/**
* Constructor for an include
*
* @param theValue
* The <code>_include</code> value, e.g. "Patient:name"
* @param theRecurse
* Should the include recurse
*/
public Include(String theValue, boolean theRecurse) {
myValue = theValue;
myRecurse = theRecurse;
myImmutable = false;
}
/**
* Constructor for an include
*
* @param theValue
* The <code>_include</code> value, e.g. "Patient:name"
* @param theRecurse
* Should the include recurse
*/
public Include(String theValue, boolean theRecurse, boolean theImmutable) {
myValue = theValue;
myRecurse = theRecurse;
myImmutable = theImmutable;
}
/**
* Creates a copy of this include with non-recurse behaviour
*/
public Include asNonRecursive() {
return new Include(myValue, false);
}
/**
* Creates a copy of this include with recurse behaviour
*/
public Include asRecursive() {
return new Include(myValue, true);
}
/**
* See the note on equality on the {@link Include class documentation}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Include other = (Include) obj;
if (myRecurse != other.myRecurse) {
return false;
}
if (myValue == null) {
if (other.myValue != null) {
return false;
}
} else if (!myValue.equals(other.myValue)) {
return false;
}
return true;
}
/**
* Returns the portion of the value before the first colon
*/
public String getParamType() {
int firstColon = myValue.indexOf(':');
if (firstColon == -1 || firstColon == myValue.length() - 1) {
return null;
}
return myValue.substring(0, firstColon);
}
/**
* Returns the portion of the value after the first colon but before the second colon
*/
public String getParamName() {
int firstColon = myValue.indexOf(':');
if (firstColon == -1 || firstColon == myValue.length() - 1) {
return null;
}
int secondColon = myValue.indexOf(':', firstColon + 1);
if (secondColon != -1) {
return myValue.substring(firstColon + 1, secondColon);
}
return myValue.substring(firstColon + 1);
}
/**
* Returns the portion of the string after the second colon, or null if there are not two colons in the value.
*/
public String getParamTargetType() {
int firstColon = myValue.indexOf(':');
if (firstColon == -1 || firstColon == myValue.length() - 1) {
return null;
}
int secondColon = myValue.indexOf(':', firstColon + 1);
if (secondColon != -1) {
return myValue.substring(secondColon + 1);
}
return null;
}
public String getValue() {
return myValue;
}
/**
* See the note on equality on the {@link Include class documentation}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (myRecurse ? 1231 : 1237);
result = prime * result + ((myValue == null) ? 0 : myValue.hashCode());
return result;
}
/**
* Is this object {@link #toLocked() locked}?
*/
public boolean isLocked() {
return myImmutable;
}
public boolean isRecurse() {
return myRecurse;
}
public void setRecurse(boolean theRecurse) {
myRecurse = theRecurse;
}
public void setValue(String theValue) {
if (myImmutable) {
throw new IllegalStateException("Can not change the value of this include");
}
myValue = theValue;
}
/**
* Return a new
*/
public Include toLocked() {
Include retVal = new Include(myValue, myRecurse, true);
return retVal;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("value", myValue);
builder.append("recurse", myRecurse);
return builder.toString();
}
/**
* Creates and returns a new copy of this Include with the given type. The following table shows what will be
* returned:
* <table>
* <tr>
* <th>Initial Contents</th>
* <th>theResourceType</th>
* <th>Output</th>
* </tr>
* <tr>
* <td>Patient:careProvider</th>
* <th>Organization</th>
* <th>Patient:careProvider:Organization</th>
* </tr>
* <tr>
* <td>Patient:careProvider:Practitioner</th>
* <th>Organization</th>
* <th>Patient:careProvider:Organization</th>
* </tr>
* <tr>
* <td>Patient</th>
* <th>(any)</th>
* <th>{@link IllegalStateException}</th>
* </tr>
* </table>
*
* @param theResourceType
* The resource type (e.g. "Organization")
* @return A new copy of the include. Note that if this include is {@link #toLocked() locked}, the returned include
* will be too
*/
public Include withType(String theResourceType) {
StringBuilder b = new StringBuilder();
String paramType = getParamType();
String paramName = getParamName();
if (isBlank(paramType) || isBlank(paramName)) {
throw new IllegalStateException("This include does not contain a value in the format [ResourceType]:[paramName]");
}
b.append(paramType);
b.append(":");
b.append(paramName);
if (isNotBlank(theResourceType)) {
b.append(':');
b.append(theResourceType);
}
Include retVal = new Include(b.toString(), myRecurse, myImmutable);
return retVal;
}
}